[MOVED FROM GST-P-FARSIGHT] Do wierd casting of the volume to make MSVC happy
[platform/upstream/gstreamer.git] / gst / dtmf / gstrtpdtmfsrc.c
1 /* GStreamer RTP DTMF source
2  *
3  * gstrtpdtmfsrc.c:
4  *
5  * Copyright (C) <2007> Nokia Corporation.
6  *   Contact: Zeeshan Ali <zeeshan.ali@nokia.com>
7  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
8  *               2000,2005 Wim Taymans <wim@fluendo.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 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  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 /**
27  * SECTION:element-rtpdtmfsrc
28  * @short_description: Generates RTP DTMF packets
29  *
30  * <refsect2>
31  *
32  * <para>
33  * The RTPDTMFSrc element generates RTP DTMF (RFC 2833) event packets on request
34  * from application. The application communicates the beginning and end of a
35  * DTMF event using custom upstream gstreamer events. To report a DTMF event, an
36  * application must send an event of type GST_EVENT_CUSTOM_UPSTREAM, having a
37  * structure of name "dtmf-event" with fields set according to the following
38  * table:
39  * </para>
40  *
41  * <para>
42  * <informaltable>
43  * <tgroup cols='4'>
44  * <colspec colname='Name' />
45  * <colspec colname='Type' />
46  * <colspec colname='Possible values' />
47  * <colspec colname='Purpose' />
48  *
49  * <thead>
50  * <row>
51  * <entry>Name</entry>
52  * <entry>GType</entry>
53  * <entry>Possible values</entry>
54  * <entry>Purpose</entry>
55  * </row>
56  * </thead>
57  *
58  * <tbody>
59  * <row>
60  * <entry>type</entry>
61  * <entry>G_TYPE_INT</entry>
62  * <entry>0-1</entry>
63  * <entry>The application uses this field to specify which of the two methods
64  * specified in RFC 2833 to use. The value should be 0 for tones and 1 for
65  * named events. Tones are specified by their frequencies and events are specied
66  * by their number. This element can only take events as input. Do not confuse
67  * with "method" which specified the output.
68  * </entry>
69  * </row>
70  * <row>
71  * <entry>number</entry>
72  * <entry>G_TYPE_INT</entry>
73  * <entry>0-16</entry>
74  * <entry>The event number.</entry>
75  * </row>
76  * <row>
77  * <entry>volume</entry>
78  * <entry>G_TYPE_INT</entry>
79  * <entry>0-36</entry>
80  * <entry>This field describes the power level of the tone, expressed in dBm0
81  * after dropping the sign. Power levels range from 0 to -63 dBm0. The range of
82  * valid DTMF is from 0 to -36 dBm0. Can be omitted if start is set to FALSE.
83  * </entry>
84  * </row>
85  * <row>
86  * <entry>start</entry>
87  * <entry>G_TYPE_BOOLEAN</entry>
88  * <entry>True or False</entry>
89  * <entry>Whether the event is starting or ending.</entry>
90  * </row>
91  * <row>
92  * <entry>method</entry>
93  * <entry>G_TYPE_INT</entry>
94  * <entry>1</entry>
95  * <entry>The method used for sending event, this element will react if this
96  * field is absent or 1.
97  * </entry>
98  * </row>
99  * </tbody>
100  * </tgroup>
101  * </informaltable>
102  * </para>
103  *
104  * <para>For example, the following code informs the pipeline (and in turn, the
105  * RTPDTMFSrc element inside the pipeline) about the start of an RTP DTMF named
106  * event '1' of volume -25 dBm0:
107  * </para>
108  *
109  * <para>
110  * <programlisting>
111  * structure = gst_structure_new ("dtmf-event",
112  *                    "type", G_TYPE_INT, 1,
113  *                    "number", G_TYPE_INT, 1,
114  *                    "volume", G_TYPE_INT, 25,
115  *                    "start", G_TYPE_BOOLEAN, TRUE, NULL);
116  *
117  * event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
118  * gst_element_send_event (pipeline, event);
119  * </programlisting>
120  * </para>
121  *
122  * </refsect2>
123  */
124
125 #ifdef HAVE_CONFIG_H
126 #  include "config.h"
127 #endif
128
129 #include <stdlib.h>
130 #include <string.h>
131
132 #include <glib.h>
133
134 #include "gstrtpdtmfsrc.h"
135
136 #define GST_RTP_DTMF_TYPE_EVENT  1
137 #define DEFAULT_PACKET_INTERVAL  50 /* ms */
138 #define MIN_PACKET_INTERVAL      10 /* ms */
139 #define MAX_PACKET_INTERVAL      50 /* ms */
140 #define DEFAULT_SSRC             -1
141 #define DEFAULT_PT               96
142 #define DEFAULT_TIMESTAMP_OFFSET -1
143 #define DEFAULT_SEQNUM_OFFSET    -1
144 #define DEFAULT_CLOCK_RATE       8000
145 #define MIN_EVENT                0
146 #define MAX_EVENT                16
147 #define MIN_EVENT_STRING         "0"
148 #define MAX_EVENT_STRING         "16"
149 #define MIN_VOLUME               0
150 #define MAX_VOLUME               36
151
152 #define MIN_INTER_DIGIT_INTERVAL 50 /* ms */
153 #define MIN_PULSE_DURATION       70 /* ms */
154
155 #define DEFAULT_PACKET_REDUNDANCY 1
156 #define MIN_PACKET_REDUNDANCY 1
157 #define MAX_PACKET_REDUNDANCY 5
158
159 /* elementfactory information */
160 static const GstElementDetails gst_rtp_dtmf_src_details =
161 GST_ELEMENT_DETAILS ("RTP DTMF packet generator",
162     "Source/Network",
163     "Generates RTP DTMF packets",
164     "Zeeshan Ali <zeeshan.ali@nokia.com>");
165
166 GST_DEBUG_CATEGORY_STATIC (gst_rtp_dtmf_src_debug);
167 #define GST_CAT_DEFAULT gst_rtp_dtmf_src_debug
168
169 /* signals and args */
170 enum
171 {
172   /* FILL ME */
173   LAST_SIGNAL
174 };
175
176 enum
177 {
178   PROP_0,
179   PROP_SSRC,
180   PROP_TIMESTAMP_OFFSET,
181   PROP_SEQNUM_OFFSET,
182   PROP_PT,
183   PROP_CLOCK_RATE,
184   PROP_TIMESTAMP,
185   PROP_SEQNUM,
186   PROP_INTERVAL,
187   PROP_REDUNDANCY
188 };
189
190 static GstStaticPadTemplate gst_rtp_dtmf_src_template =
191 GST_STATIC_PAD_TEMPLATE ("src",
192     GST_PAD_SRC,
193     GST_PAD_ALWAYS,
194     GST_STATIC_CAPS ("application/x-rtp, "
195         "media = (string) \"audio\", "
196         "payload = (int) [ 96, 127 ], "
197         "clock-rate = (int) [ 0, MAX ], "
198         "ssrc = (int) [ 0, MAX ], "
199         "encoding-name = (string) \"TELEPHONE-EVENT\"")
200     /*  "events = (string) \"0-15\" */
201
202     );
203
204
205 GST_BOILERPLATE (GstRTPDTMFSrc, gst_rtp_dtmf_src, GstBaseSrc,
206     GST_TYPE_BASE_SRC);
207
208
209 static void gst_rtp_dtmf_src_base_init (gpointer g_class);
210 static void gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass);
211 static void gst_rtp_dtmf_src_finalize (GObject * object);
212
213
214 static void gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id,
215     const GValue * value, GParamSpec * pspec);
216 static void gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id,
217     GValue * value, GParamSpec * pspec);
218 static gboolean gst_rtp_dtmf_src_handle_event (GstBaseSrc *basesrc,
219     GstEvent * event);
220 static GstStateChangeReturn gst_rtp_dtmf_src_change_state (GstElement * element,
221     GstStateChange transition);
222 static void gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc,
223     gint event_number, gint event_volume);
224 static void gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc);
225
226 static gboolean gst_rtp_dtmf_src_unlock (GstBaseSrc *src);
227 static gboolean gst_rtp_dtmf_src_unlock_stop (GstBaseSrc *src);
228 static GstFlowReturn gst_rtp_dtmf_src_create (GstBaseSrc * basesrc,
229     guint64 offset, guint length, GstBuffer ** buffer);
230 static gboolean gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc);
231
232
233 static void
234 gst_rtp_dtmf_src_base_init (gpointer g_class)
235 {
236   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
237
238   GST_DEBUG_CATEGORY_INIT (gst_rtp_dtmf_src_debug,
239           "rtpdtmfsrc", 0, "rtpdtmfsrc element");
240
241   gst_element_class_add_pad_template (element_class,
242       gst_static_pad_template_get (&gst_rtp_dtmf_src_template));
243
244   gst_element_class_set_details (element_class, &gst_rtp_dtmf_src_details);
245 }
246
247 static void
248 gst_rtp_dtmf_src_class_init (GstRTPDTMFSrcClass * klass)
249 {
250   GObjectClass *gobject_class;
251   GstBaseSrcClass *gstbasesrc_class;
252   GstElementClass *gstelement_class;
253
254   gobject_class = G_OBJECT_CLASS (klass);
255   gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
256   gstelement_class = GST_ELEMENT_CLASS (klass);
257
258   parent_class = g_type_class_peek_parent (klass);
259
260   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_finalize);
261   gobject_class->set_property =
262       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_set_property);
263   gobject_class->get_property =
264       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_get_property);
265
266   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP,
267       g_param_spec_uint ("timestamp", "Timestamp",
268           "The RTP timestamp of the last processed packet",
269           0, G_MAXUINT, 0, G_PARAM_READABLE));
270   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM,
271       g_param_spec_uint ("seqnum", "Sequence number",
272           "The RTP sequence number of the last processed packet",
273           0, G_MAXUINT, 0, G_PARAM_READABLE));
274   g_object_class_install_property (G_OBJECT_CLASS (klass),
275       PROP_TIMESTAMP_OFFSET, g_param_spec_int ("timestamp-offset",
276           "Timestamp Offset",
277           "Offset to add to all outgoing timestamps (-1 = random)", -1,
278           G_MAXINT, DEFAULT_TIMESTAMP_OFFSET, G_PARAM_READWRITE));
279   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET,
280       g_param_spec_int ("seqnum-offset", "Sequence number Offset",
281           "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXINT,
282           DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE));
283   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CLOCK_RATE,
284       g_param_spec_uint ("clock-rate", "clockrate",
285           "The clock-rate at which to generate the dtmf packets",
286           0, G_MAXUINT, DEFAULT_CLOCK_RATE, G_PARAM_READWRITE));
287   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC,
288       g_param_spec_uint ("ssrc", "SSRC",
289           "The SSRC of the packets (-1 == random)",
290           0, G_MAXUINT, DEFAULT_SSRC, G_PARAM_READWRITE));
291   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT,
292       g_param_spec_uint ("pt", "payload type",
293           "The payload type of the packets",
294           0, 0x80, DEFAULT_PT, G_PARAM_READWRITE));
295   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INTERVAL,
296       g_param_spec_uint ("interval", "Interval between rtp packets",
297           "Interval in ms between two rtp packets", MIN_PACKET_INTERVAL,
298           MAX_PACKET_INTERVAL, DEFAULT_PACKET_INTERVAL, G_PARAM_READWRITE));
299   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_REDUNDANCY,
300       g_param_spec_uint ("packet-redundancy", "Packet Redundancy",
301           "Number of packets to send to indicate start and stop dtmf events",
302           MIN_PACKET_REDUNDANCY, MAX_PACKET_REDUNDANCY,
303           DEFAULT_PACKET_REDUNDANCY, G_PARAM_READWRITE));
304
305   gstelement_class->change_state =
306       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_change_state);
307
308   gstbasesrc_class->unlock =
309       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_unlock);
310   gstbasesrc_class->unlock_stop =
311       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_unlock_stop);
312
313   gstbasesrc_class->event =
314       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_handle_event);
315   gstbasesrc_class->create =
316       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_create);
317   gstbasesrc_class->negotiate =
318       GST_DEBUG_FUNCPTR (gst_rtp_dtmf_src_negotiate);
319 }
320
321 static void
322 gst_rtp_dtmf_src_init (GstRTPDTMFSrc * object, GstRTPDTMFSrcClass * g_class)
323 {
324   gst_base_src_set_format (GST_BASE_SRC (object), GST_FORMAT_TIME);
325   gst_base_src_set_live (GST_BASE_SRC (object), TRUE);
326
327   object->ssrc = DEFAULT_SSRC;
328   object->seqnum_offset = DEFAULT_SEQNUM_OFFSET;
329   object->ts_offset = DEFAULT_TIMESTAMP_OFFSET;
330   object->pt = DEFAULT_PT;
331   object->clock_rate = DEFAULT_CLOCK_RATE;
332   object->interval = DEFAULT_PACKET_INTERVAL;
333   object->packet_redundancy = DEFAULT_PACKET_REDUNDANCY;
334
335   object->event_queue = g_async_queue_new ();
336   object->payload = NULL;
337
338   GST_DEBUG_OBJECT (object, "init done");
339 }
340
341 static void
342 gst_rtp_dtmf_src_finalize (GObject * object)
343 {
344   GstRTPDTMFSrc *dtmfsrc;
345
346   dtmfsrc = GST_RTP_DTMF_SRC (object);
347
348   if (dtmfsrc->event_queue) {
349     g_async_queue_unref (dtmfsrc->event_queue);
350     dtmfsrc->event_queue = NULL;
351   }
352
353
354   G_OBJECT_CLASS (parent_class)->finalize (object);
355 }
356
357 static gboolean
358 gst_rtp_dtmf_src_handle_dtmf_event (GstRTPDTMFSrc *dtmfsrc,
359         const GstStructure * event_structure)
360 {
361   gint event_type;
362   gboolean start;
363   gint method;
364
365   if (!gst_structure_get_int (event_structure, "type", &event_type) ||
366           !gst_structure_get_boolean (event_structure, "start", &start) ||
367           event_type != GST_RTP_DTMF_TYPE_EVENT)
368     goto failure;
369
370   if (gst_structure_get_int (event_structure, "method", &method)) {
371     if (method != 1) {
372       goto failure;
373     }
374   }
375
376   if (start) {
377     gint event_number;
378     gint event_volume;
379
380     if (!gst_structure_get_int (event_structure, "number", &event_number) ||
381             !gst_structure_get_int (event_structure, "volume", &event_volume))
382       goto failure;
383
384     GST_DEBUG_OBJECT (dtmfsrc, "Received start event %d with volume %d",
385             event_number, event_volume);
386     gst_rtp_dtmf_src_add_start_event (dtmfsrc, event_number, event_volume);
387   }
388
389   else {
390     GST_DEBUG_OBJECT (dtmfsrc, "Received stop event");
391     gst_rtp_dtmf_src_add_stop_event (dtmfsrc);
392   }
393
394   return TRUE;
395 failure:
396   return FALSE;
397 }
398
399 static gboolean
400 gst_rtp_dtmf_src_handle_custom_upstream (GstRTPDTMFSrc *dtmfsrc,
401     GstEvent * event)
402 {
403   gboolean result = FALSE;
404   gchar *struct_str;
405   const GstStructure *structure;
406
407   GstState state;
408   GstStateChangeReturn ret;
409
410   ret = gst_element_get_state (GST_ELEMENT (dtmfsrc), &state, NULL, 0);
411   if (ret != GST_STATE_CHANGE_SUCCESS || state != GST_STATE_PLAYING) {
412     GST_DEBUG_OBJECT (dtmfsrc, "Received event while not in PLAYING state");
413     goto ret;
414   }
415
416   GST_DEBUG_OBJECT (dtmfsrc, "Received event is of our interest");
417   structure = gst_event_get_structure (event);
418   struct_str = gst_structure_to_string (structure);
419   GST_DEBUG_OBJECT (dtmfsrc, "Event has structure %s", struct_str);
420   g_free (struct_str);
421   if (structure && gst_structure_has_name (structure, "dtmf-event"))
422     result = gst_rtp_dtmf_src_handle_dtmf_event (dtmfsrc, structure);
423
424 ret:
425   return result;
426 }
427
428 static gboolean
429 gst_rtp_dtmf_src_handle_event (GstBaseSrc *basesrc, GstEvent * event)
430 {
431   GstRTPDTMFSrc *dtmfsrc;
432   gboolean result = FALSE;
433
434   dtmfsrc = GST_RTP_DTMF_SRC (basesrc);
435
436   GST_DEBUG_OBJECT (dtmfsrc, "Received an event on the src pad");
437   if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) {
438     result = gst_rtp_dtmf_src_handle_custom_upstream (dtmfsrc, event);
439   }
440
441   return result;
442 }
443
444 static void
445 gst_rtp_dtmf_src_set_property (GObject * object, guint prop_id,
446     const GValue * value, GParamSpec * pspec)
447 {
448   GstRTPDTMFSrc *dtmfsrc;
449
450   dtmfsrc = GST_RTP_DTMF_SRC (object);
451
452   switch (prop_id) {
453     case PROP_TIMESTAMP_OFFSET:
454       dtmfsrc->ts_offset = g_value_get_int (value);
455       break;
456     case PROP_SEQNUM_OFFSET:
457       dtmfsrc->seqnum_offset = g_value_get_int (value);
458       break;
459     case PROP_CLOCK_RATE:
460       dtmfsrc->clock_rate = g_value_get_uint (value);
461       dtmfsrc->dirty = TRUE;
462       break;
463     case PROP_SSRC:
464       dtmfsrc->ssrc = g_value_get_uint (value);
465       break;
466     case PROP_PT:
467       dtmfsrc->pt = g_value_get_uint (value);
468       dtmfsrc->dirty = TRUE;
469       break;
470     case PROP_INTERVAL:
471       dtmfsrc->interval = g_value_get_uint (value);
472       break;
473     case PROP_REDUNDANCY:
474       dtmfsrc->packet_redundancy = g_value_get_uint (value);
475       break;
476     default:
477       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
478       break;
479   }
480 }
481
482 static void
483 gst_rtp_dtmf_src_get_property (GObject * object, guint prop_id, GValue * value,
484     GParamSpec * pspec)
485 {
486   GstRTPDTMFSrc *dtmfsrc;
487
488   dtmfsrc = GST_RTP_DTMF_SRC (object);
489
490   switch (prop_id) {
491     case PROP_TIMESTAMP_OFFSET:
492       g_value_set_int (value, dtmfsrc->ts_offset);
493       break;
494     case PROP_SEQNUM_OFFSET:
495       g_value_set_int (value, dtmfsrc->seqnum_offset);
496       break;
497     case PROP_CLOCK_RATE:
498       g_value_set_uint (value, dtmfsrc->clock_rate);
499       break;
500     case PROP_SSRC:
501       g_value_set_uint (value, dtmfsrc->ssrc);
502       break;
503     case PROP_PT:
504       g_value_set_uint (value, dtmfsrc->pt);
505       break;
506     case PROP_TIMESTAMP:
507       g_value_set_uint (value, dtmfsrc->rtp_timestamp);
508       break;
509     case PROP_SEQNUM:
510       g_value_set_uint (value, dtmfsrc->seqnum);
511       break;
512     case PROP_INTERVAL:
513       g_value_set_uint (value, dtmfsrc->interval);
514       break;
515     case PROP_REDUNDANCY:
516       g_value_set_uint (value, dtmfsrc->packet_redundancy);
517       break;
518     default:
519       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
520       break;
521   }
522 }
523
524 static void
525 gst_rtp_dtmf_src_set_stream_lock (GstRTPDTMFSrc *dtmfsrc, gboolean lock)
526 {
527    GstEvent *event;
528    GstStructure *structure;
529
530    structure = gst_structure_new ("stream-lock",
531                       "lock", G_TYPE_BOOLEAN, lock, NULL);
532
533    event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure);
534    if (!gst_pad_push_event (GST_BASE_SRC_PAD (dtmfsrc), event)) {
535      GST_WARNING_OBJECT (dtmfsrc, "stream-lock event not handled");
536    }
537
538 }
539
540 static void
541 gst_rtp_dtmf_prepare_timestamps (GstRTPDTMFSrc *dtmfsrc)
542 {
543   GstClock *clock;
544   GstClockTime base_time;
545
546 #ifdef MAEMO_BROKEN
547   base_time = 0;
548 #else
549   base_time = gst_element_get_base_time (GST_ELEMENT (dtmfsrc));
550 #endif
551
552   clock = gst_element_get_clock (GST_ELEMENT (dtmfsrc));
553   if (clock != NULL) {
554     dtmfsrc->timestamp = gst_clock_get_time (clock)
555         + (MIN_INTER_DIGIT_INTERVAL * GST_MSECOND) - base_time;
556     dtmfsrc->start_timestamp = dtmfsrc->timestamp;
557     gst_object_unref (clock);
558   } else {
559     gchar *dtmf_name = gst_element_get_name (dtmfsrc);
560     GST_ERROR_OBJECT (dtmfsrc, "No clock set for element %s", dtmf_name);
561     dtmfsrc->timestamp = GST_CLOCK_TIME_NONE;
562     g_free (dtmf_name);
563   }
564
565   dtmfsrc->rtp_timestamp = dtmfsrc->ts_base +
566       gst_util_uint64_scale_int (
567           gst_segment_to_running_time (&GST_BASE_SRC (dtmfsrc)->segment,
568               GST_FORMAT_TIME, dtmfsrc->timestamp),
569           dtmfsrc->clock_rate, GST_SECOND);
570 }
571
572
573 static void
574 gst_rtp_dtmf_src_add_start_event (GstRTPDTMFSrc *dtmfsrc, gint event_number,
575     gint event_volume)
576 {
577
578   GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent));
579   event->event_type = RTP_DTMF_EVENT_TYPE_START;
580
581   event->payload = g_new0 (GstRTPDTMFPayload, 1);
582   event->payload->event = CLAMP (event_number, MIN_EVENT, MAX_EVENT);
583   event->payload->volume = CLAMP (event_volume, MIN_VOLUME, MAX_VOLUME);
584   event->payload->duration = dtmfsrc->interval * dtmfsrc->clock_rate / 1000;
585
586   g_async_queue_push (dtmfsrc->event_queue, event);
587 }
588
589 static void
590 gst_rtp_dtmf_src_add_stop_event (GstRTPDTMFSrc *dtmfsrc)
591 {
592
593   GstRTPDTMFSrcEvent * event = g_malloc (sizeof(GstRTPDTMFSrcEvent));
594   event->event_type = RTP_DTMF_EVENT_TYPE_STOP;
595
596   g_async_queue_push (dtmfsrc->event_queue, event);
597 }
598
599
600 static void
601 gst_rtp_dtmf_prepare_rtp_headers (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf)
602 {
603   gst_rtp_buffer_set_ssrc (buf, dtmfsrc->current_ssrc);
604   gst_rtp_buffer_set_payload_type (buf, dtmfsrc->pt);
605   /* Only the very first packet gets a marker */
606   if (dtmfsrc->first_packet) {
607     gst_rtp_buffer_set_marker (buf, TRUE);
608   } else if (dtmfsrc->last_packet) {
609     dtmfsrc->payload->e = 1;
610   }
611
612   dtmfsrc->seqnum++;
613   gst_rtp_buffer_set_seq (buf, dtmfsrc->seqnum);
614
615   /* timestamp of RTP header */
616   gst_rtp_buffer_set_timestamp (buf, dtmfsrc->rtp_timestamp);
617 }
618
619 static void
620 gst_rtp_dtmf_prepare_buffer_data (GstRTPDTMFSrc *dtmfsrc, GstBuffer *buf)
621 {
622   GstRTPDTMFPayload *payload;
623
624   gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc, buf);
625
626   /* timestamp and duration of GstBuffer */
627   /* Redundant buffer have no duration ... */
628   if (dtmfsrc->redundancy_count > 1)
629     GST_BUFFER_DURATION (buf) = 0;
630   else
631     GST_BUFFER_DURATION (buf) = dtmfsrc->interval * GST_MSECOND;
632   GST_BUFFER_TIMESTAMP (buf) = dtmfsrc->timestamp;
633
634   dtmfsrc->timestamp += GST_BUFFER_DURATION (buf);
635
636   payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (buf);
637
638   /* copy payload and convert to network-byte order */
639   g_memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload));
640   /* Force the packet duration to a certain minumum
641    * if its the end of the event
642    */
643   if (payload->e &&
644       payload->duration < MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000 )
645     payload->duration = MIN_PULSE_DURATION * dtmfsrc->clock_rate / 1000;
646
647   payload->duration = g_htons (payload->duration);
648
649
650   /* duration of DTMF payloadfor the NEXT packet */
651   /* not updated for redundant packets */
652   if (dtmfsrc->redundancy_count == 0)
653     dtmfsrc->payload->duration +=
654         dtmfsrc->interval * dtmfsrc->clock_rate / 1000;
655
656 }
657
658 static GstBuffer *
659 gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc *dtmfsrc)
660 {
661   GstBuffer *buf = NULL;
662
663   /* create buffer to hold the payload */
664   buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0);
665
666   gst_rtp_dtmf_prepare_buffer_data (dtmfsrc, buf);
667
668   /* Set caps on the buffer before pushing it */
669   gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (dtmfsrc)));
670
671   return buf;
672 }
673
674 static GstFlowReturn
675 gst_rtp_dtmf_src_create (GstBaseSrc * basesrc, guint64 offset,
676     guint length, GstBuffer ** buffer)
677 {
678   GstRTPDTMFSrcEvent *event;
679   GstRTPDTMFSrc * dtmfsrc;
680   GstClock *clock;
681   GstClockID *clockid;
682   GstClockReturn clockret;
683
684   dtmfsrc = GST_RTP_DTMF_SRC (basesrc);
685
686   do {
687
688     if (dtmfsrc->payload == NULL) {
689       GST_DEBUG_OBJECT (dtmfsrc, "popping");
690       event = g_async_queue_pop (dtmfsrc->event_queue);
691
692       GST_DEBUG_OBJECT (dtmfsrc, "popped %d", event->event_type);
693
694       switch (event->event_type) {
695         case RTP_DTMF_EVENT_TYPE_STOP:
696           GST_WARNING_OBJECT (dtmfsrc,
697               "Received a DTMF stop event when already stopped");
698           break;
699
700         case RTP_DTMF_EVENT_TYPE_START:
701           dtmfsrc->first_packet = TRUE;
702           dtmfsrc->last_packet = FALSE;
703           /* Set the redundancy on the first packet */
704           dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
705           gst_rtp_dtmf_prepare_timestamps (dtmfsrc);
706
707           /* Don't forget to get exclusive access to the stream */
708           gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, TRUE);
709
710           dtmfsrc->payload = event->payload;
711           break;
712
713         case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
714           /*
715            * We're pushing it back because it has to stay in there until
716            * the task is really paused (and the queue will then be flushed
717            */
718           GST_OBJECT_LOCK (dtmfsrc);
719           if (dtmfsrc->paused) {
720             g_async_queue_push (dtmfsrc->event_queue, event);
721             goto paused_locked;
722           }
723           GST_OBJECT_UNLOCK (dtmfsrc);
724           break;
725       }
726
727       g_free (event);
728     } else if (!dtmfsrc->first_packet && !dtmfsrc->last_packet &&
729         (dtmfsrc->timestamp - dtmfsrc->start_timestamp)/GST_MSECOND >=
730         MIN_PULSE_DURATION) {
731       GST_DEBUG_OBJECT (dtmfsrc, "try popping");
732       event = g_async_queue_try_pop (dtmfsrc->event_queue);
733
734
735       if (event != NULL) {
736         GST_DEBUG_OBJECT (dtmfsrc, "try popped %d", event->event_type);
737
738         switch (event->event_type) {
739           case RTP_DTMF_EVENT_TYPE_START:
740             GST_WARNING_OBJECT (dtmfsrc,
741                 "Received two consecutive DTMF start events");
742             break;
743
744           case RTP_DTMF_EVENT_TYPE_STOP:
745             dtmfsrc->first_packet = FALSE;
746             dtmfsrc->last_packet = TRUE;
747             /* Set the redundancy on the last packet */
748             dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
749             break;
750
751           case RTP_DTMF_EVENT_TYPE_PAUSE_TASK:
752             /*
753              * We're pushing it back because it has to stay in there until
754              * the task is really paused (and the queue will then be flushed)
755              */
756             GST_DEBUG_OBJECT (dtmfsrc, "pushing pause_task...");
757             GST_OBJECT_LOCK (dtmfsrc);
758             if (dtmfsrc->paused) {
759               g_async_queue_push (dtmfsrc->event_queue, event);
760               goto paused_locked;
761             }
762             GST_OBJECT_UNLOCK (dtmfsrc);
763             break;
764         }
765         g_free (event);
766       }
767     }
768   } while (dtmfsrc->payload == NULL);
769
770
771   GST_DEBUG_OBJECT (dtmfsrc, "Processed events, now lets wait on the clock");
772
773   clock = gst_element_get_clock (GST_ELEMENT (basesrc));
774
775 #ifdef MAEMO_BROKEN
776   clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp);
777 #else
778   clockid = gst_clock_new_single_shot_id (clock, dtmfsrc->timestamp +
779       gst_element_get_base_time (GST_ELEMENT (dtmfsrc)));
780 #endif
781   gst_object_unref (clock);
782
783   GST_OBJECT_LOCK (dtmfsrc);
784   if (!dtmfsrc->paused) {
785     dtmfsrc->clockid = clockid;
786     GST_OBJECT_UNLOCK (dtmfsrc);
787
788     clockret = gst_clock_id_wait (clockid, NULL);
789
790     GST_OBJECT_LOCK (dtmfsrc);
791     if (dtmfsrc->paused)
792       clockret = GST_CLOCK_UNSCHEDULED;
793   } else  {
794     clockret = GST_CLOCK_UNSCHEDULED;
795   }
796   gst_clock_id_unref (clockid);
797   dtmfsrc->clockid = NULL;
798   GST_OBJECT_UNLOCK (dtmfsrc);
799
800   if (clockret == GST_CLOCK_UNSCHEDULED) {
801     goto paused;
802   }
803
804  send_last:
805
806   if (dtmfsrc->dirty)
807     if (!gst_rtp_dtmf_src_negotiate (basesrc))
808       return GST_FLOW_NOT_NEGOTIATED;
809
810   /* create buffer to hold the payload */
811   *buffer = gst_rtp_dtmf_src_create_next_rtp_packet (dtmfsrc);
812
813   if (dtmfsrc->redundancy_count)
814     dtmfsrc->redundancy_count--;
815
816   /* Only the very first one has a marker */
817   dtmfsrc->first_packet = FALSE;
818
819   /* This is the end of the event */
820   if (dtmfsrc->last_packet == TRUE && dtmfsrc->redundancy_count == 0) {
821
822     /* Don't forget to release the stream lock */
823     gst_rtp_dtmf_src_set_stream_lock (dtmfsrc, FALSE);
824
825     g_free (dtmfsrc->payload);
826     dtmfsrc->payload = NULL;
827
828     dtmfsrc->last_packet = FALSE;
829   }
830
831   return GST_FLOW_OK;
832
833  paused_locked:
834
835   GST_OBJECT_UNLOCK (dtmfsrc);
836
837  paused:
838
839   if (dtmfsrc->payload) {
840     dtmfsrc->first_packet = FALSE;
841     dtmfsrc->last_packet = TRUE;
842     /* Set the redundanc on the last packet */
843     dtmfsrc->redundancy_count = dtmfsrc->packet_redundancy;
844     goto send_last;
845   } else {
846     return GST_FLOW_WRONG_STATE;
847   }
848 }
849
850
851 static gboolean
852 gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc)
853 {
854   GstCaps *srccaps, *peercaps;
855   GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (basesrc);
856   gboolean ret;
857
858   /* fill in the defaults, there properties cannot be negotiated. */
859   srccaps = gst_caps_new_simple ("application/x-rtp",
860       "media", G_TYPE_STRING, "audio",
861       "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT", NULL);
862
863   /* the peer caps can override some of the defaults */
864   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
865   if (peercaps == NULL) {
866     /* no peer caps, just add the other properties */
867     gst_caps_set_simple (srccaps,
868         "payload", G_TYPE_INT, dtmfsrc->pt,
869         "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc,
870         "clock-base", G_TYPE_UINT, dtmfsrc->ts_base,
871         "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate,
872         "seqnum-base", G_TYPE_UINT, dtmfsrc->seqnum_base, NULL);
873
874     GST_DEBUG_OBJECT (dtmfsrc, "no peer caps: %" GST_PTR_FORMAT, srccaps);
875   } else {
876     GstCaps *temp;
877     GstStructure *s;
878     const GValue *value;
879     gint pt;
880     gint clock_rate;
881
882     /* peer provides caps we can use to fixate, intersect. This always returns a
883      * writable caps. */
884     temp = gst_caps_intersect (srccaps, peercaps);
885     gst_caps_unref (srccaps);
886     gst_caps_unref (peercaps);
887
888     if (!temp) {
889       GST_DEBUG_OBJECT (dtmfsrc, "Could not get intersection with peer caps");
890       return FALSE;
891     }
892
893     if (gst_caps_is_empty (temp)) {
894       GST_DEBUG_OBJECT (dtmfsrc, "Intersection with peer caps is empty");
895       gst_caps_unref (temp);
896       return FALSE;
897     }
898
899     /* now fixate, start by taking the first caps */
900     gst_caps_truncate (temp);
901     srccaps = temp;
902
903     /* get first structure */
904     s = gst_caps_get_structure (srccaps, 0);
905
906     if (gst_structure_get_int (s, "payload", &pt)) {
907       /* use peer pt */
908       dtmfsrc->pt = pt;
909       GST_LOG_OBJECT (dtmfsrc, "using peer pt %d", pt);
910     } else {
911       if (gst_structure_has_field (s, "payload")) {
912         /* can only fixate if there is a field */
913         gst_structure_fixate_field_nearest_int (s, "payload",
914             dtmfsrc->pt);
915         gst_structure_get_int (s, "payload", &pt);
916         GST_LOG_OBJECT (dtmfsrc, "using peer pt %d", pt);
917       } else {
918         /* no pt field, use the internal pt */
919         pt = dtmfsrc->pt;
920         gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
921         GST_LOG_OBJECT (dtmfsrc, "using internal pt", pt);
922       }
923     }
924
925     if (gst_structure_get_int (s, "clock-rate", &clock_rate))
926     {
927       dtmfsrc->clock_rate = clock_rate;
928       GST_LOG_OBJECT (dtmfsrc, "using clock-rate from caps %d",
929           dtmfsrc->clock_rate);
930     } else {
931       GST_LOG_OBJECT (dtmfsrc, "using existing clock-rate %d",
932           dtmfsrc->clock_rate);
933     }
934     gst_structure_set (s, "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate,
935         NULL);
936
937
938     if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) {
939       value = gst_structure_get_value (s, "ssrc");
940       dtmfsrc->current_ssrc = g_value_get_uint (value);
941       GST_LOG_OBJECT (dtmfsrc, "using peer ssrc %08x", dtmfsrc->current_ssrc);
942     } else {
943       /* FIXME, fixate_nearest_uint would be even better */
944       gst_structure_set (s, "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc, NULL);
945       GST_LOG_OBJECT (dtmfsrc, "using internal ssrc %08x",
946           dtmfsrc->current_ssrc);
947     }
948
949     if (gst_structure_has_field_typed (s, "clock-base", G_TYPE_UINT)) {
950       value = gst_structure_get_value (s, "clock-base");
951       dtmfsrc->ts_base = g_value_get_uint (value);
952       GST_LOG_OBJECT (dtmfsrc, "using peer clock-base %u", dtmfsrc->ts_base);
953     } else {
954       /* FIXME, fixate_nearest_uint would be even better */
955       gst_structure_set (s, "clock-base", G_TYPE_UINT, dtmfsrc->ts_base, NULL);
956       GST_LOG_OBJECT (dtmfsrc, "using internal clock-base %u",
957           dtmfsrc->ts_base);
958     }
959     if (gst_structure_has_field_typed (s, "seqnum-base", G_TYPE_UINT)) {
960       value = gst_structure_get_value (s, "seqnum-base");
961       dtmfsrc->seqnum_base = g_value_get_uint (value);
962       GST_LOG_OBJECT (dtmfsrc, "using peer seqnum-base %u",
963           dtmfsrc->seqnum_base);
964     } else {
965       /* FIXME, fixate_nearest_uint would be even better */
966       gst_structure_set (s, "seqnum-base", G_TYPE_UINT, dtmfsrc->seqnum_base,
967           NULL);
968       GST_LOG_OBJECT (dtmfsrc, "using internal seqnum-base %u",
969           dtmfsrc->seqnum_base);
970     }
971     GST_DEBUG_OBJECT (dtmfsrc, "with peer caps: %" GST_PTR_FORMAT, srccaps);
972   }
973
974   ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), srccaps);
975   gst_caps_unref (srccaps);
976
977   dtmfsrc->dirty = FALSE;
978
979   return ret;
980
981 }
982
983
984 static void
985 gst_rtp_dtmf_src_ready_to_paused (GstRTPDTMFSrc *dtmfsrc)
986 {
987   if (dtmfsrc->ssrc == -1)
988     dtmfsrc->current_ssrc = g_random_int ();
989   else
990     dtmfsrc->current_ssrc = dtmfsrc->ssrc;
991
992   if (dtmfsrc->seqnum_offset == -1)
993     dtmfsrc->seqnum_base = g_random_int_range (0, G_MAXUINT16);
994   else
995     dtmfsrc->seqnum_base = dtmfsrc->seqnum_offset;
996   dtmfsrc->seqnum = dtmfsrc->seqnum_base;
997
998   if (dtmfsrc->ts_offset == -1)
999     dtmfsrc->ts_base = g_random_int ();
1000   else
1001     dtmfsrc->ts_base = dtmfsrc->ts_offset;
1002
1003 }
1004
1005 static GstStateChangeReturn
1006 gst_rtp_dtmf_src_change_state (GstElement * element, GstStateChange transition)
1007 {
1008   GstRTPDTMFSrc *dtmfsrc;
1009   GstStateChangeReturn result;
1010   gboolean no_preroll = FALSE;
1011   GstRTPDTMFSrcEvent *event= NULL;
1012
1013   dtmfsrc = GST_RTP_DTMF_SRC (element);
1014
1015   switch (transition) {
1016     case GST_STATE_CHANGE_READY_TO_PAUSED:
1017       gst_rtp_dtmf_src_ready_to_paused (dtmfsrc);
1018
1019       /* Flushing the event queue */
1020       while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL)
1021         g_free (event);
1022
1023       no_preroll = TRUE;
1024       break;
1025     default:
1026       break;
1027   }
1028
1029   if ((result =
1030           GST_ELEMENT_CLASS (parent_class)->change_state (element,
1031               transition)) == GST_STATE_CHANGE_FAILURE)
1032     goto failure;
1033
1034   switch (transition) {
1035     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1036       no_preroll = TRUE;
1037       break;
1038     case GST_STATE_CHANGE_PAUSED_TO_READY:
1039
1040      /* Flushing the event queue */
1041       while ((event = g_async_queue_try_pop (dtmfsrc->event_queue)) != NULL)
1042         g_free (event);
1043
1044       /* Indicate that we don't do PRE_ROLL */
1045       break;
1046
1047     default:
1048       break;
1049   }
1050
1051   if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
1052     result = GST_STATE_CHANGE_NO_PREROLL;
1053
1054   return result;
1055
1056   /* ERRORS */
1057 failure:
1058   {
1059     GST_ERROR_OBJECT (dtmfsrc, "parent failed state change");
1060     return result;
1061   }
1062 }
1063
1064
1065 static gboolean
1066 gst_rtp_dtmf_src_unlock (GstBaseSrc *src) {
1067   GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (src);
1068   GstRTPDTMFSrcEvent *event = NULL;
1069
1070   GST_DEBUG_OBJECT (dtmfsrc, "Called unlock");
1071
1072   GST_OBJECT_LOCK (dtmfsrc);
1073   dtmfsrc->paused = TRUE;
1074   if (dtmfsrc->clockid) {
1075     gst_clock_id_unschedule (dtmfsrc->clockid);
1076   }
1077   GST_OBJECT_UNLOCK (dtmfsrc);
1078
1079   GST_DEBUG_OBJECT (dtmfsrc, "Pushing the PAUSE_TASK event on unlock request");
1080   event = g_malloc (sizeof(GstRTPDTMFSrcEvent));
1081   event->event_type = RTP_DTMF_EVENT_TYPE_PAUSE_TASK;
1082   g_async_queue_push (dtmfsrc->event_queue, event);
1083
1084   return TRUE;
1085 }
1086
1087
1088 static gboolean
1089 gst_rtp_dtmf_src_unlock_stop (GstBaseSrc *src) {
1090   GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (src);
1091
1092   GST_DEBUG_OBJECT (dtmfsrc, "Unlock stopped");
1093
1094   GST_OBJECT_LOCK (dtmfsrc);
1095   dtmfsrc->paused = FALSE;
1096   GST_OBJECT_UNLOCK (dtmfsrc);
1097
1098   return TRUE;
1099 }
1100
1101 gboolean
1102 gst_rtp_dtmf_src_plugin_init (GstPlugin * plugin)
1103 {
1104   return gst_element_register (plugin, "rtpdtmfsrc",
1105       GST_RANK_NONE, GST_TYPE_RTP_DTMF_SRC);
1106 }