Remove dummy plugin_init. Remove some undefined entries from doc- section file. Add...
[platform/upstream/gstreamer.git] / gst / debug / gstnavseek.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David Schleef <ds@schleef.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * This file was (probably) generated from gstnavseek.c,
23  * gstnavseek.c,v 1.7 2003/11/08 02:48:59 dschleef Exp 
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "gstnavseek.h"
31 #include <string.h>
32 #include <math.h>
33
34 enum
35 {
36   ARG_0,
37   ARG_SEEKOFFSET
38 };
39
40 GstStaticPadTemplate navseek_src_template = GST_STATIC_PAD_TEMPLATE ("src",
41     GST_PAD_SRC,
42     GST_PAD_ALWAYS,
43     GST_STATIC_CAPS_ANY);
44
45 GstStaticPadTemplate navseek_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
46     GST_PAD_SINK,
47     GST_PAD_ALWAYS,
48     GST_STATIC_CAPS_ANY);
49
50 static const GstElementDetails navseek_details =
51 GST_ELEMENT_DETAILS ("Seek based on left-right arrows",
52     "Filter/Video",
53     "Seek based on navigation keys left-right",
54     "Jan Schmidt <thaytan@mad.scientist.com>");
55
56 static gboolean gst_navseek_event (GstBaseTransform * trans, GstEvent * event);
57 static GstFlowReturn gst_navseek_transform_ip (GstBaseTransform * basetrans,
58     GstBuffer * buf);
59 static gboolean gst_navseek_handle_src_event (GstPad * pad, GstEvent * event);
60 static gboolean gst_navseek_stop (GstBaseTransform * trans);
61 static gboolean gst_navseek_start (GstBaseTransform * trans);
62
63 static void gst_navseek_set_property (GObject * object, guint prop_id,
64     const GValue * value, GParamSpec * pspec);
65 static void gst_navseek_get_property (GObject * object, guint prop_id,
66     GValue * value, GParamSpec * pspec);
67
68 GST_BOILERPLATE (GstNavSeek, gst_navseek, GstBaseTransform,
69     GST_TYPE_BASE_TRANSFORM);
70
71 static void
72 gst_navseek_base_init (gpointer g_class)
73 {
74   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
75
76   gst_element_class_add_pad_template (element_class,
77       gst_static_pad_template_get (&navseek_sink_template));
78   gst_element_class_add_pad_template (element_class,
79       gst_static_pad_template_get (&navseek_src_template));
80
81   gst_element_class_set_details (element_class, &navseek_details);
82 }
83
84 static void
85 gst_navseek_class_init (GstNavSeekClass * klass)
86 {
87   GstBaseTransformClass *gstbasetrans_class;
88   GObjectClass *gobject_class;
89
90   gobject_class = G_OBJECT_CLASS (klass);
91   gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
92
93   gobject_class->set_property = gst_navseek_set_property;
94   gobject_class->get_property = gst_navseek_get_property;
95
96   g_object_class_install_property (gobject_class,
97       ARG_SEEKOFFSET, g_param_spec_double ("seek-offset", "Seek Offset",
98           "Time in seconds to seek by", 0.0, G_MAXDOUBLE, 5.0,
99           G_PARAM_READWRITE));
100
101   gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_navseek_event);
102   gstbasetrans_class->transform_ip =
103       GST_DEBUG_FUNCPTR (gst_navseek_transform_ip);
104   gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_navseek_start);
105   gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_navseek_stop);
106 }
107
108 static void
109 gst_navseek_init (GstNavSeek * navseek, GstNavSeekClass * g_class)
110 {
111   gst_pad_set_event_function (GST_BASE_TRANSFORM (navseek)->srcpad,
112       GST_DEBUG_FUNCPTR (gst_navseek_handle_src_event));
113
114   gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (navseek), TRUE);
115
116   navseek->seek_offset = 5.0;
117   navseek->loop = FALSE;
118   navseek->grab_seg_start = FALSE;
119   navseek->grab_seg_end = FALSE;
120   navseek->segment_start = GST_CLOCK_TIME_NONE;
121   navseek->segment_end = GST_CLOCK_TIME_NONE;
122 }
123
124 static void
125 gst_navseek_seek (GstNavSeek * navseek, gint64 offset)
126 {
127   GstFormat peer_format = GST_FORMAT_TIME;
128   gboolean ret;
129   GstPad *peer_pad;
130   gint64 peer_value;
131
132   /* Query for the current time then attempt to set to time + offset */
133   peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
134   ret = gst_pad_query_position (peer_pad, &peer_format, &peer_value);
135
136   if (ret && peer_format == GST_FORMAT_TIME) {
137     GstEvent *event;
138
139     peer_value += offset;
140     if (peer_value < 0)
141       peer_value = 0;
142
143     event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
144         GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
145         GST_SEEK_TYPE_SET, peer_value, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
146
147     gst_pad_send_event (peer_pad, event);
148   }
149
150   gst_object_unref (peer_pad);
151 }
152
153 static void
154 gst_navseek_segseek (GstNavSeek * navseek)
155 {
156   GstEvent *event;
157   GstPad *peer_pad;
158
159   if ((navseek->segment_start == GST_CLOCK_TIME_NONE) ||
160       (navseek->segment_end == GST_CLOCK_TIME_NONE) ||
161       (!GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad))) {
162     return;
163   }
164
165   if (navseek->loop) {
166     event =
167         gst_event_new_seek (1.0, GST_FORMAT_TIME,
168         GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT,
169         GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
170         navseek->segment_end);
171   } else {
172     event =
173         gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE,
174         GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
175         navseek->segment_end);
176   }
177
178   peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
179   gst_pad_send_event (peer_pad, event);
180   gst_object_unref (peer_pad);
181 }
182
183 static gboolean
184 gst_navseek_handle_src_event (GstPad * pad, GstEvent * event)
185 {
186   GstNavSeek *navseek;
187   gboolean ret = TRUE;
188
189   navseek = GST_NAVSEEK (GST_PAD_PARENT (pad));
190
191   switch (GST_EVENT_TYPE (event)) {
192     case GST_EVENT_NAVIGATION:
193       /* Check for a keyup and convert left/right to a seek event */
194     {
195       const GstStructure *structure;
196       const gchar *event_type;
197
198       structure = gst_event_get_structure (event);
199       g_return_val_if_fail (structure != NULL, FALSE);
200
201       event_type = gst_structure_get_string (structure, "event");
202       g_return_val_if_fail (event_type != NULL, FALSE);
203
204       if (strcmp (event_type, "key-press") == 0) {
205         const gchar *key;
206
207         key = gst_structure_get_string (structure, "key");
208         g_return_val_if_fail (key != NULL, FALSE);
209
210         if (strcmp (key, "Left") == 0) {
211           /* Seek backward by 5 secs */
212           gst_navseek_seek (navseek, -1.0 * navseek->seek_offset * GST_SECOND);
213         } else if (strcmp (key, "Right") == 0) {
214           /* Seek forward */
215           gst_navseek_seek (navseek, navseek->seek_offset * GST_SECOND);
216         } else if (strcmp (key, "s") == 0) {
217           /* Grab the next frame as the start frame of a segment */
218           navseek->grab_seg_start = TRUE;
219         } else if (strcmp (key, "e") == 0) {
220           /* Grab the next frame as the end frame of a segment */
221           navseek->grab_seg_end = TRUE;
222         } else if (strcmp (key, "l") == 0) {
223           /* Toggle the loop flag. If we have both start and end segment times send a seek */
224           navseek->loop = !navseek->loop;
225           gst_navseek_segseek (navseek);
226         }
227       } else {
228         break;
229       }
230       gst_event_unref (event);
231       event = NULL;
232     }
233       break;
234     default:
235       break;
236   }
237
238   if (event && GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad)) {
239     GstPad *peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
240
241     ret = gst_pad_send_event (peer_pad, event);
242     gst_object_unref (peer_pad);
243   }
244
245   return ret;
246 }
247
248 static void
249 gst_navseek_set_property (GObject * object, guint prop_id,
250     const GValue * value, GParamSpec * pspec)
251 {
252   GstNavSeek *navseek = GST_NAVSEEK (object);
253
254   switch (prop_id) {
255     case ARG_SEEKOFFSET:
256       GST_OBJECT_LOCK (navseek);
257       navseek->seek_offset = g_value_get_double (value);
258       GST_OBJECT_UNLOCK (navseek);
259       break;
260     default:
261       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
262       break;
263   }
264 }
265
266 static void
267 gst_navseek_get_property (GObject * object, guint prop_id,
268     GValue * value, GParamSpec * pspec)
269 {
270   GstNavSeek *navseek = GST_NAVSEEK (object);
271
272   switch (prop_id) {
273     case ARG_SEEKOFFSET:
274       GST_OBJECT_LOCK (navseek);
275       g_value_set_double (value, navseek->seek_offset);
276       GST_OBJECT_UNLOCK (navseek);
277       break;
278     default:
279       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
280       break;
281   }
282 }
283
284 static gboolean
285 gst_navseek_event (GstBaseTransform * trans, GstEvent * event)
286 {
287   GstNavSeek *navseek = GST_NAVSEEK (trans);
288
289   switch (GST_EVENT_TYPE (event)) {
290     case GST_EVENT_EOS:
291       GST_OBJECT_LOCK (navseek);
292       if (navseek->loop)
293         gst_navseek_segseek (navseek);
294       GST_OBJECT_UNLOCK (navseek);
295       break;
296     default:
297       break;
298   }
299   return GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event);
300 }
301
302 static GstFlowReturn
303 gst_navseek_transform_ip (GstBaseTransform * basetrans, GstBuffer * buf)
304 {
305   GstNavSeek *navseek = GST_NAVSEEK (basetrans);
306
307   GST_OBJECT_LOCK (navseek);
308
309   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
310     if (navseek->grab_seg_start) {
311       navseek->segment_start = GST_BUFFER_TIMESTAMP (buf);
312       navseek->segment_end = GST_CLOCK_TIME_NONE;
313       navseek->grab_seg_start = FALSE;
314     }
315
316     if (navseek->grab_seg_end) {
317       navseek->segment_end = GST_BUFFER_TIMESTAMP (buf);
318       navseek->grab_seg_end = FALSE;
319       gst_navseek_segseek (navseek);
320     }
321   }
322
323   GST_OBJECT_UNLOCK (navseek);
324
325   return GST_FLOW_OK;
326 }
327
328 static gboolean
329 gst_navseek_start (GstBaseTransform * trans)
330 {
331   /* anything we should be doing here? */
332   return TRUE;
333 }
334
335 static gboolean
336 gst_navseek_stop (GstBaseTransform * trans)
337 {
338   /* anything we should be doing here? */
339   return TRUE;
340 }