compatibility fix for new GST_DEBUG stuff.
[platform/upstream/gst-plugins-good.git] / gst / monoscope / gstmonoscope.c
1 /* gstmonoscope.c: implementation of monoscope drawing element
2  * Copyright (C) <2002> Richard Boulton <richard@tartarus.org>
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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <config.h>
24 #include <gst/gst.h>
25
26 #include "monoscope.h"
27
28 #define GST_TYPE_MONOSCOPE (gst_monoscope_get_type())
29 #define GST_MONOSCOPE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MONOSCOPE,GstMonoscope))
30 #define GST_MONOSCOPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MONOSCOPE,GstMonoscope))
31 #define GST_IS_MONOSCOPE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MONOSCOPE))
32 #define GST_IS_MONOSCOPE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MONOSCOPE))
33
34 typedef struct _GstMonoscope GstMonoscope;
35 typedef struct _GstMonoscopeClass GstMonoscopeClass;
36
37 struct _GstMonoscope {
38   GstElement element;
39
40   /* pads */
41   GstPad *sinkpad,*srcpad;
42   GstBufferPool *peerpool;
43
44   /* the timestamp of the next frame */
45   guint64 next_time;
46   gint16 datain[512];
47
48   /* video state */
49   gint fps;
50   gint width;
51   gint height;
52   gboolean first_buffer;
53
54   /* visualisation state */
55   struct monoscope_state * visstate;
56 };
57
58 struct _GstMonoscopeClass {
59   GstElementClass parent_class;
60 };
61
62 GType gst_monoscope_get_type(void);
63
64
65 /* elementfactory information */
66 static GstElementDetails gst_monoscope_details = {
67   "Monoscope",
68   "Visualization",
69   "GPL",
70   "Displays a highly stabilised waveform of audio input",
71   VERSION,
72   "Richard Boulton <richard@tartarus.org>",
73   "(C) 2002",
74 };
75
76 /* signals and args */
77 enum {
78   /* FILL ME */
79   LAST_SIGNAL
80 };
81
82 enum {
83   ARG_0,
84   ARG_WIDTH,
85   ARG_HEIGHT,
86   ARG_FPS,
87   /* FILL ME */
88 };
89
90 GST_PAD_TEMPLATE_FACTORY (src_template,
91   "src",
92   GST_PAD_SRC,
93   GST_PAD_ALWAYS,
94   GST_CAPS_NEW (
95     "monoscopesrc",
96     "video/raw",
97       "format",         GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
98       "bpp",            GST_PROPS_INT (32),
99       "depth",          GST_PROPS_INT (32),
100       "endianness",     GST_PROPS_INT (G_BYTE_ORDER),
101       "red_mask",       GST_PROPS_INT (0xff0000),
102       "green_mask",     GST_PROPS_INT (0xff00),
103       "blue_mask",      GST_PROPS_INT (0xff),
104       "width",          GST_PROPS_INT_RANGE (16, 4096),
105       "height",         GST_PROPS_INT_RANGE (16, 4096)
106   )
107 )
108
109 GST_PAD_TEMPLATE_FACTORY (sink_template,
110   "sink",                                       /* the name of the pads */
111   GST_PAD_SINK,                         /* type of the pad */
112   GST_PAD_ALWAYS,                               /* ALWAYS/SOMETIMES */
113   GST_CAPS_NEW (
114     "monoscopesink",                            /* the name of the caps */
115     "audio/raw",                                /* the mime type of the caps */
116        /* Properties follow: */
117       "format",     GST_PROPS_STRING ("int"),
118       "law",        GST_PROPS_INT (0),
119       "endianness", GST_PROPS_INT (G_BYTE_ORDER),
120       "signed",     GST_PROPS_BOOLEAN (TRUE),
121       "width",      GST_PROPS_INT (16),
122       "depth",      GST_PROPS_INT (16),
123       "rate",       GST_PROPS_INT_RANGE (8000, 96000),
124       "channels",   GST_PROPS_INT (1)
125   )
126 )
127
128
129 static void             gst_monoscope_class_init        (GstMonoscopeClass *klass);
130 static void             gst_monoscope_init              (GstMonoscope *monoscope);
131
132 static void             gst_monoscope_set_property      (GObject *object, guint prop_id, 
133                                                  const GValue *value, GParamSpec *pspec);
134 static void             gst_monoscope_get_property      (GObject *object, guint prop_id, 
135                                                  GValue *value, GParamSpec *pspec);
136
137 static void             gst_monoscope_chain             (GstPad *pad, GstBuffer *buf);
138
139 static GstPadLinkReturn 
140                         gst_monoscope_sinkconnect       (GstPad *pad, GstCaps *caps);
141
142 static GstElementClass *parent_class = NULL;
143
144 GType
145 gst_monoscope_get_type (void)
146 {
147   static GType type = 0;
148
149   if (!type) {
150     static const GTypeInfo info = {
151       sizeof (GstMonoscopeClass),      
152       NULL,      
153       NULL,      
154       (GClassInitFunc) gst_monoscope_class_init,
155       NULL,
156       NULL,
157       sizeof (GstMonoscope),
158       0,
159       (GInstanceInitFunc) gst_monoscope_init,
160     };
161     type = g_type_register_static (GST_TYPE_ELEMENT, "GstMonoscope", &info, 0);
162   }
163   return type;
164 }
165
166 static void
167 gst_monoscope_class_init(GstMonoscopeClass *klass)
168 {
169   GObjectClass *gobject_class;
170   GstElementClass *gstelement_class;
171
172   gobject_class = (GObjectClass*) klass;
173   gstelement_class = (GstElementClass*) klass;
174
175   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
176
177   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH,
178     g_param_spec_int ("width","Width","The Width",
179                        1, 2048, 256, G_PARAM_READWRITE));
180   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEIGHT,
181     g_param_spec_int ("height","Height","The height",
182                        1, 2048, 128, G_PARAM_READWRITE));
183   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FPS,
184     g_param_spec_int ("fps","FPS","Frames per second",
185                        1, 100, 25, G_PARAM_READWRITE));
186
187   gobject_class->set_property = gst_monoscope_set_property;
188   gobject_class->get_property = gst_monoscope_get_property;
189 }
190
191 static void
192 gst_monoscope_init (GstMonoscope *monoscope)
193 {
194   /* create the sink and src pads */
195   monoscope->sinkpad = gst_pad_new_from_template (
196                   GST_PAD_TEMPLATE_GET (sink_template ), "sink");
197   monoscope->srcpad = gst_pad_new_from_template (
198                   GST_PAD_TEMPLATE_GET (src_template ), "src");
199   gst_element_add_pad (GST_ELEMENT (monoscope), monoscope->sinkpad);
200   gst_element_add_pad (GST_ELEMENT (monoscope), monoscope->srcpad);
201
202   gst_pad_set_chain_function (monoscope->sinkpad, gst_monoscope_chain);
203   gst_pad_set_link_function (monoscope->sinkpad, gst_monoscope_sinkconnect);
204
205   monoscope->next_time = 0;
206   monoscope->peerpool = NULL;
207
208   /* reset the initial video state */
209   monoscope->first_buffer = TRUE;
210   monoscope->width = 256;
211   monoscope->height = 128;
212   monoscope->fps = 25; /* desired frame rate */
213
214 }
215
216 static GstPadLinkReturn
217 gst_monoscope_sinkconnect (GstPad *pad, GstCaps *caps)
218 {
219   GstMonoscope *monoscope;
220   monoscope = GST_MONOSCOPE (gst_pad_get_parent (pad));
221
222   if (!GST_CAPS_IS_FIXED (caps)) {
223     return GST_PAD_LINK_DELAYED;
224   }
225
226   return GST_PAD_LINK_OK;
227 }
228
229 static void
230 gst_monoscope_chain (GstPad *pad, GstBuffer *bufin)
231 {
232   GstMonoscope *monoscope;
233   GstBuffer *bufout;
234   guint32 samples_in;
235   gint16 *data;
236   gint i;
237
238   monoscope = GST_MONOSCOPE (gst_pad_get_parent (pad));
239
240   GST_DEBUG ("Monoscope: chainfunc called");
241
242   samples_in = GST_BUFFER_SIZE (bufin) / sizeof (gint16);
243
244   GST_DEBUG ("input buffer has %d samples", samples_in);
245
246   /* FIXME: should really select the first 1024 samples after the timestamp. */
247   if (GST_BUFFER_TIMESTAMP (bufin) < monoscope->next_time || samples_in < 1024) {
248     GST_DEBUG ("timestamp is %" G_GUINT64_FORMAT ": want >= %" G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (bufin), monoscope->next_time);
249     gst_buffer_unref (bufin);
250     return;
251   }
252
253   data = (gint16 *) GST_BUFFER_DATA (bufin);
254   /* FIXME: Select samples in a better way. */
255   for (i=0; i < 512; i++) {
256     monoscope->datain[i] = *data++;
257   }
258
259   if (monoscope->first_buffer) {
260     GstCaps *caps;
261
262     monoscope->visstate = monoscope_init (monoscope->width, monoscope->height);
263     g_assert(monoscope->visstate != 0);
264     GST_DEBUG ("making new pad");
265
266     caps = GST_CAPS_NEW (
267                      "monoscopesrc",
268                      "video/raw",
269                        "format",        GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")), 
270                        "bpp",           GST_PROPS_INT (32), 
271                        "depth",         GST_PROPS_INT (32), 
272                        "endianness",    GST_PROPS_INT (G_BYTE_ORDER), 
273                        "red_mask",      GST_PROPS_INT (0xff0000), 
274                        "green_mask",    GST_PROPS_INT (0x00ff00), 
275                        "blue_mask",     GST_PROPS_INT (0x0000ff), 
276                        "width",         GST_PROPS_INT (monoscope->width), 
277                        "height",        GST_PROPS_INT (monoscope->height)
278                    );
279
280     if (gst_pad_try_set_caps (monoscope->srcpad, caps) <= 0) {
281       gst_element_error (GST_ELEMENT (monoscope), "could not set caps");
282       return;
283     }
284     monoscope->first_buffer = FALSE;
285   }
286
287   bufout = gst_buffer_new ();
288   GST_BUFFER_SIZE (bufout) = monoscope->width * monoscope->height * 4;
289   GST_BUFFER_DATA (bufout) = (guchar *) monoscope_update (monoscope->visstate, monoscope->datain);
290   GST_BUFFER_TIMESTAMP (bufout) = monoscope->next_time;
291   GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_DONTFREE);
292
293   monoscope->next_time += GST_SECOND / monoscope->fps;
294
295   gst_pad_push (monoscope->srcpad, bufout);
296
297   gst_buffer_unref (bufin);
298
299   GST_DEBUG ("Monoscope: exiting chainfunc");
300
301 }
302
303 static void
304 gst_monoscope_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
305 {
306   GstMonoscope *monoscope;
307
308   /* it's not null if we got it, but it might not be ours */
309   g_return_if_fail (GST_IS_MONOSCOPE (object));
310   monoscope = GST_MONOSCOPE (object);
311
312   switch (prop_id) {
313     case ARG_WIDTH:
314       monoscope->width = g_value_get_int (value);
315       break;
316     case ARG_HEIGHT:
317       monoscope->height = g_value_get_int (value);
318       break;
319     case ARG_FPS:
320       monoscope->fps = g_value_get_int (value);
321       break;
322     default:
323       break;
324   }
325 }
326
327 static void
328 gst_monoscope_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
329 {
330   GstMonoscope *monoscope;
331
332   /* it's not null if we got it, but it might not be ours */
333   g_return_if_fail (GST_IS_MONOSCOPE (object));
334   monoscope = GST_MONOSCOPE (object);
335
336   switch (prop_id) {
337     case ARG_WIDTH:
338       g_value_set_int (value, monoscope->width);
339       break;
340     case ARG_HEIGHT:
341       g_value_set_int (value, monoscope->height);
342       break;
343     case ARG_FPS:
344       g_value_set_int (value, monoscope->fps);
345       break;
346     default:
347       break;
348   }
349 }
350
351 static gboolean
352 plugin_init (GModule *module, GstPlugin *plugin)
353 {
354   GstElementFactory *factory;
355
356   /* create an elementfactory for the monoscope element */
357   factory = gst_element_factory_new("monoscope",GST_TYPE_MONOSCOPE,
358                                    &gst_monoscope_details);
359   g_return_val_if_fail(factory != NULL, FALSE);
360
361   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_template));
362   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_template));
363
364   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
365
366   return TRUE;
367 }
368
369 GstPluginDesc plugin_desc = {
370   GST_VERSION_MAJOR,
371   GST_VERSION_MINOR,
372   "monoscope",
373   plugin_init
374 };