add default bufferpool, clean up some code, add bufferpool testing to fakesrc
[platform/upstream/gstreamer.git] / gst / elements / gstfakesrc.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstfakesrc.c: 
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <gstfakesrc.h>
28
29
30 GstElementDetails gst_fakesrc_details = {
31   "Fake Source",
32   "Source",
33   "Push empty (no data) buffers around",
34   VERSION,
35   "Erik Walthinsen <omega@cse.ogi.edu>\n"
36   "Wim Taymans <wim.taymans@chello.be>",
37   "(C) 1999",
38 };
39
40
41 /* FakeSrc signals and args */
42 enum {
43   /* FILL ME */
44   SIGNAL_HANDOFF,
45   LAST_SIGNAL
46 };
47
48 enum {
49   ARG_0,
50   ARG_NUM_SOURCES,
51   ARG_LOOP_BASED,
52   ARG_OUTPUT,
53   ARG_DATA,
54   ARG_SIZETYPE,
55   ARG_SIZEMIN,
56   ARG_SIZEMAX,
57   ARG_FILLTYPE,
58   ARG_PATTERN,
59   ARG_NUM_BUFFERS,
60   ARG_EOS,
61   ARG_SILENT,
62   ARG_DUMP,
63   ARG_PARENTSIZE,
64   ARG_LAST_MESSAGE,
65 };
66
67 GST_PAD_TEMPLATE_FACTORY (fakesrc_src_factory,
68   "src%d",
69   GST_PAD_SRC,
70   GST_PAD_REQUEST,
71   NULL                  /* no caps */
72 );
73
74 #define GST_TYPE_FAKESRC_OUTPUT (gst_fakesrc_output_get_type())
75 static GType
76 gst_fakesrc_output_get_type (void) 
77 {
78   static GType fakesrc_output_type = 0;
79   static GEnumValue fakesrc_output[] = {
80     { FAKESRC_FIRST_LAST_LOOP,          "1", "First-Last loop"},
81     { FAKESRC_LAST_FIRST_LOOP,          "2", "Last-First loop"},
82     { FAKESRC_PING_PONG,                "3", "Ping-Pong"},
83     { FAKESRC_ORDERED_RANDOM,           "4", "Ordered Random"},
84     { FAKESRC_RANDOM,                   "5", "Random"},
85     { FAKESRC_PATTERN_LOOP,             "6", "Patttern loop"},
86     { FAKESRC_PING_PONG_PATTERN,        "7", "Ping-Pong Pattern"},
87     { FAKESRC_GET_ALWAYS_SUCEEDS,       "8", "'_get' Always succeeds"},
88     {0, NULL, NULL},
89   };
90   if (!fakesrc_output_type) {
91     fakesrc_output_type = g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
92   }
93   return fakesrc_output_type;
94 }
95
96 #define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
97 static GType
98 gst_fakesrc_data_get_type (void) 
99 {
100   static GType fakesrc_data_type = 0;
101   static GEnumValue fakesrc_data[] = {
102     { FAKESRC_DATA_ALLOCATE,            "1", "Allocate data"},
103     { FAKESRC_DATA_SUBBUFFER,           "2", "Subbuffer data"},
104     { FAKESRC_DATA_BUFFERPOOL,          "3", "Use the default buffer pool (forces sizetype=2)"},
105     {0, NULL, NULL},
106   };
107   if (!fakesrc_data_type) {
108     fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
109   }
110   return fakesrc_data_type;
111 }
112
113 #define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
114 static GType
115 gst_fakesrc_sizetype_get_type (void) 
116 {
117   static GType fakesrc_sizetype_type = 0;
118   static GEnumValue fakesrc_sizetype[] = {
119     { FAKESRC_SIZETYPE_NULL,            "1", "Send empty buffers"},
120     { FAKESRC_SIZETYPE_FIXED,           "2", "Fixed size buffers (sizemax sized)"},
121     { FAKESRC_SIZETYPE_RANDOM,          "3", "Random sized buffers (sizemin <= size <= sizemax)"},
122     {0, NULL, NULL},
123   };
124   if (!fakesrc_sizetype_type) {
125     fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
126   }
127   return fakesrc_sizetype_type;
128 }
129
130 #define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
131 static GType
132 gst_fakesrc_filltype_get_type (void) 
133 {
134   static GType fakesrc_filltype_type = 0;
135   static GEnumValue fakesrc_filltype[] = {
136     { FAKESRC_FILLTYPE_NOTHING,         "1", "Leave data as malloced"},
137     { FAKESRC_FILLTYPE_NULL,            "2", "Fill buffers with zeros"},
138     { FAKESRC_FILLTYPE_RANDOM,          "3", "Fill buffers with random crap"},
139     { FAKESRC_FILLTYPE_PATTERN,         "4", "Fill buffers with pattern 0x00 -> 0xff"},
140     { FAKESRC_FILLTYPE_PATTERN_CONT,    "5", "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
141     {0, NULL, NULL},
142   };
143   if (!fakesrc_filltype_type) {
144     fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
145   }
146   return fakesrc_filltype_type;
147 }
148
149 static void             gst_fakesrc_class_init          (GstFakeSrcClass *klass);
150 static void             gst_fakesrc_init                (GstFakeSrc *fakesrc);
151
152 static GstPad*          gst_fakesrc_request_new_pad     (GstElement *element, GstPadTemplate *templ);
153 static void             gst_fakesrc_update_functions    (GstFakeSrc *src);
154 static void             gst_fakesrc_set_property        (GObject *object, guint prop_id, 
155                                                          const GValue *value, GParamSpec *pspec);
156 static void             gst_fakesrc_get_property        (GObject *object, guint prop_id, 
157                                                          GValue *value, GParamSpec *pspec);
158
159 static GstElementStateReturn gst_fakesrc_change_state   (GstElement *element);
160
161 static GstBuffer*       gst_fakesrc_get                 (GstPad *pad);
162 static void             gst_fakesrc_loop                (GstElement *element);
163
164 static GstElementClass *parent_class = NULL;
165 static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
166
167 GType
168 gst_fakesrc_get_type (void) 
169 {
170   static GType fakesrc_type = 0;
171
172   if (!fakesrc_type) {
173     static const GTypeInfo fakesrc_info = {
174       sizeof(GstFakeSrcClass),
175       NULL,
176       NULL,
177       (GClassInitFunc)gst_fakesrc_class_init,
178       NULL,
179       NULL,
180       sizeof(GstFakeSrc),
181       0,
182       (GInstanceInitFunc)gst_fakesrc_init,
183     };
184     fakesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFakeSrc", &fakesrc_info, 0);
185   }
186   return fakesrc_type;
187 }
188
189 static void
190 gst_fakesrc_class_init (GstFakeSrcClass *klass) 
191 {
192   GObjectClass *gobject_class;
193   GstElementClass *gstelement_class;
194
195   gobject_class = (GObjectClass*)klass;
196   gstelement_class = (GstElementClass*)klass;
197
198   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
199
200   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
201     g_param_spec_int ("num-sources", "num-sources", "Number of sources",
202                       1, G_MAXINT, 1, G_PARAM_READABLE));
203   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LOOP_BASED,
204     g_param_spec_boolean("loop-based","loop-based","Enable loop-based operation",
205                          FALSE, G_PARAM_READWRITE));
206   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT,
207     g_param_spec_enum("output","output","Output method (currently unused)",
208                       GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE));
209   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
210     g_param_spec_enum ("data", "data", "Data allocation method",
211                        GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE)); 
212   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
213     g_param_spec_enum ("sizetype", "sizetype", "How to determine buffer sizes",
214                        GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE)); 
215   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
216     g_param_spec_int ("sizemin","sizemin","Minimum buffer size",
217                       0, G_MAXINT, 0, G_PARAM_READWRITE)); 
218   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
219     g_param_spec_int ("sizemax","sizemax","Maximum buffer size",
220                       0, G_MAXINT, 4096, G_PARAM_READWRITE)); 
221   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
222     g_param_spec_int ("parentsize","parentsize","Size of parent buffer for sub-buffered allocation",
223                       0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE)); 
224   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
225     g_param_spec_enum ("filltype", "filltype", "How to fill the buffer, if at all",
226                        GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE)); 
227   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN,
228     g_param_spec_string("pattern","pattern","pattern",
229                         NULL, G_PARAM_READWRITE));
230   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NUM_BUFFERS,
231     g_param_spec_int("num-buffers","num-buffers","Number of buffers to output before sending EOS",
232                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
233   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_EOS,
234     g_param_spec_boolean("eos","eos","Send out the EOS event?",
235                          TRUE,G_PARAM_READWRITE));
236   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
237     g_param_spec_string ("last-message", "last-message", "The last status message",
238                          NULL, G_PARAM_READABLE)); 
239
240   gst_element_class_install_std_props (
241           GST_ELEMENT_CLASS (klass),
242           "silent", ARG_SILENT, G_PARAM_READWRITE,
243           "dump",   ARG_DUMP,   G_PARAM_READWRITE,
244           NULL);
245
246   gst_fakesrc_signals[SIGNAL_HANDOFF] =
247     g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
248                   G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
249                   g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
250                   G_TYPE_POINTER);
251
252   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
253   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
254
255   gstelement_class->request_new_pad =   GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
256   gstelement_class->change_state =      GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
257 }
258
259 static void 
260 gst_fakesrc_init (GstFakeSrc *fakesrc) 
261 {
262   GstPad *pad;
263
264   /* create our first output pad */
265   pad = gst_pad_new ("src", GST_PAD_SRC);
266   gst_element_add_pad (GST_ELEMENT (fakesrc), pad);
267
268   fakesrc->loop_based = FALSE;
269   gst_fakesrc_update_functions (fakesrc);
270
271   fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
272   fakesrc->num_buffers = -1;
273   fakesrc->rt_num_buffers = -1;
274   fakesrc->buffer_count = 0;
275   fakesrc->silent = FALSE;
276   fakesrc->dump = FALSE;
277   fakesrc->pattern_byte = 0x00;
278   fakesrc->need_flush = FALSE;
279   fakesrc->data = FAKESRC_DATA_ALLOCATE;
280   fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
281   fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
282   fakesrc->sizemin = 0;
283   fakesrc->sizemax = 4096;
284   fakesrc->parent = NULL;
285   fakesrc->parentsize = 4096 * 10;
286   fakesrc->last_message = NULL;
287 }
288
289 static GstPad*
290 gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
291 {
292   gchar *name;
293   GstPad *srcpad;
294   GstFakeSrc *fakesrc;
295
296   g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
297
298   if (templ->direction != GST_PAD_SRC) {
299     g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
300     return NULL;
301   }
302
303   fakesrc = GST_FAKESRC (element);
304
305   name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
306
307   srcpad = gst_pad_new_from_template (templ, name);
308   gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
309
310   g_free (name);
311
312   return srcpad;
313 }
314
315 static gboolean
316 gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
317 {
318   GstFakeSrc *src;
319
320   src = GST_FAKESRC (gst_pad_get_parent (pad));
321
322   switch (GST_EVENT_TYPE (event)) {
323     case GST_EVENT_SEEK:
324       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
325
326       if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
327         break;
328       }
329       /* else we do a flush too */
330     case GST_EVENT_FLUSH:
331       src->need_flush = TRUE;
332       break;
333     default:
334       break;
335   }
336   gst_event_unref (event);
337
338   return TRUE;
339 }
340
341 static void
342 gst_fakesrc_update_functions (GstFakeSrc *src)
343 {
344   GList *pads;
345
346   if (src->loop_based) {
347     gst_element_set_loop_function (GST_ELEMENT (src), GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
348   }
349   else {
350     gst_element_set_loop_function (GST_ELEMENT (src), NULL);
351   }
352
353   pads = GST_ELEMENT (src)->pads;
354   while (pads) {
355     GstPad *pad = GST_PAD (pads->data);
356
357     if (src->loop_based) {
358       gst_pad_set_get_function (pad, NULL);
359     }
360     else {
361       gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
362     }
363
364     gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
365     pads = g_list_next (pads);
366   }
367 }
368
369 static void
370 gst_fakesrc_alloc_parent (GstFakeSrc *src)
371 {
372   GstBuffer *buf;
373
374   buf = gst_buffer_new ();
375   GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
376   GST_BUFFER_SIZE (buf) = src->parentsize;
377
378   src->parent = buf;
379   src->parentoffset = 0;
380 }
381
382 static void
383 gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
384 {
385   GstFakeSrc *src;
386
387   /* it's not null if we got it, but it might not be ours */
388   src = GST_FAKESRC (object);
389    
390   switch (prop_id) {
391     case ARG_LOOP_BASED:
392       src->loop_based = g_value_get_boolean (value);
393       gst_fakesrc_update_functions (src);
394       break;
395     case ARG_OUTPUT:
396       g_warning ("not yet implemented");
397       break;
398     case ARG_DATA:
399       src->data = g_value_get_enum (value);
400
401       if (src->data == FAKESRC_DATA_SUBBUFFER) {
402         if (!src->parent)
403           gst_fakesrc_alloc_parent (src);
404       } else {
405         if (src->parent) {
406           gst_buffer_unref (src->parent);
407           src->parent = NULL;
408         }
409       }
410       
411       if (src->data == FAKESRC_DATA_BUFFERPOOL) {
412         if (src->sizetype != FAKESRC_SIZETYPE_FIXED)
413           g_object_set (src, "sizetype", FAKESRC_SIZETYPE_FIXED, NULL);
414         
415         if (!src->pool)
416           src->pool = gst_buffer_pool_get_default (src->sizemax, 10);
417       } else {
418         if (src->pool) {
419           gst_buffer_pool_free (src->pool);
420           src->pool = NULL;
421         }
422       }
423       break;
424     case ARG_SIZETYPE:
425       src->sizetype = g_value_get_enum (value);
426       break;
427     case ARG_SIZEMIN:
428       src->sizemin = g_value_get_int (value);
429       break;
430     case ARG_SIZEMAX:
431       src->sizemax = g_value_get_int (value);
432       break;
433     case ARG_PARENTSIZE:
434       src->parentsize = g_value_get_int (value);
435       break;
436     case ARG_FILLTYPE:
437       src->filltype = g_value_get_enum (value);
438       break;
439     case ARG_PATTERN:
440       break;
441     case ARG_NUM_BUFFERS:
442       src->num_buffers = g_value_get_int (value);
443       break;
444     case ARG_EOS:
445       src->eos = g_value_get_boolean (value);
446       GST_INFO (0, "will EOS on next buffer");
447       break;
448     case ARG_SILENT:
449       src->silent = g_value_get_boolean (value);
450       break;
451     case ARG_DUMP:
452       src->dump = g_value_get_boolean (value);
453       break;
454     default:
455       break;
456   }
457 }
458
459 static void 
460 gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
461 {
462   GstFakeSrc *src;
463    
464   /* it's not null if we got it, but it might not be ours */
465   g_return_if_fail (GST_IS_FAKESRC (object));
466   
467   src = GST_FAKESRC (object);
468    
469   switch (prop_id) {
470     case ARG_NUM_SOURCES:
471       g_value_set_int (value, GST_ELEMENT (src)->numsrcpads);
472       break;
473     case ARG_LOOP_BASED:
474       g_value_set_boolean (value, src->loop_based);
475       break;
476     case ARG_OUTPUT:
477       g_value_set_enum (value, src->output);
478       break;
479     case ARG_DATA:
480       g_value_set_enum (value, src->data);
481       break;
482     case ARG_SIZETYPE:
483       g_value_set_enum (value, src->sizetype);
484       break;
485     case ARG_SIZEMIN:
486       g_value_set_int (value, src->sizemin);
487       break;
488     case ARG_SIZEMAX:
489       g_value_set_int (value, src->sizemax);
490       break;
491     case ARG_PARENTSIZE:
492       g_value_set_int (value, src->parentsize);
493       break;
494     case ARG_FILLTYPE:
495       g_value_set_enum (value, src->filltype);
496       break;
497     case ARG_PATTERN:
498       g_value_set_string (value, src->pattern);
499       break;
500     case ARG_NUM_BUFFERS:
501       g_value_set_int (value, src->num_buffers);
502       break;
503     case ARG_EOS:
504       g_value_set_boolean (value, src->eos);
505       break;
506     case ARG_SILENT:
507       g_value_set_boolean (value, src->silent);
508       break;
509     case ARG_DUMP:
510       g_value_set_boolean (value, src->dump);
511       break;
512     case ARG_LAST_MESSAGE:
513       g_value_set_string (value, src->last_message);
514       break;
515     default:
516       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
517       break;
518   }
519 }
520
521 static void
522 gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
523 {
524   if (GST_BUFFER_SIZE (buf) == 0) 
525     return;
526
527   switch (src->filltype) {
528     case FAKESRC_FILLTYPE_NULL:
529       memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
530       break;
531     case FAKESRC_FILLTYPE_RANDOM:
532     {
533       gint i;
534       guint8 *ptr = GST_BUFFER_DATA (buf);
535
536       for (i = GST_BUFFER_SIZE (buf); i; i--) {
537         *ptr++ = (gint8)((255.0)*rand()/(RAND_MAX));
538       }
539       break;
540     }
541     case FAKESRC_FILLTYPE_PATTERN:
542       src->pattern_byte = 0x00;
543     case FAKESRC_FILLTYPE_PATTERN_CONT:
544     {
545       gint i;
546       guint8 *ptr = GST_BUFFER_DATA (buf);
547
548       for (i = GST_BUFFER_SIZE (buf); i; i--) {
549         *ptr++ = src->pattern_byte++;
550       }
551       break;
552     }
553     case FAKESRC_FILLTYPE_NOTHING:
554     default:
555       break;
556   }
557 }
558
559 static GstBuffer*
560 gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
561 {
562   GstBuffer *buf;
563
564   buf = gst_buffer_new ();
565   GST_BUFFER_SIZE(buf) = size;
566
567   if (size != 0) { 
568     switch (src->filltype) {
569       case FAKESRC_FILLTYPE_NOTHING:
570         GST_BUFFER_DATA(buf) = g_malloc (size);
571         break;
572       case FAKESRC_FILLTYPE_NULL:
573         GST_BUFFER_DATA(buf) = g_malloc0 (size);
574         break;
575       case FAKESRC_FILLTYPE_RANDOM:
576       case FAKESRC_FILLTYPE_PATTERN:
577       case FAKESRC_FILLTYPE_PATTERN_CONT:
578       default:
579         GST_BUFFER_DATA(buf) = g_malloc (size);
580         gst_fakesrc_prepare_buffer (src, buf);
581         break;
582     }
583   }
584
585   return buf;
586 }
587
588 static guint
589 gst_fakesrc_get_size (GstFakeSrc *src)
590 {
591   guint size;
592
593   switch (src->sizetype) {
594     case FAKESRC_SIZETYPE_FIXED:
595       size = src->sizemax;
596       break;
597     case FAKESRC_SIZETYPE_RANDOM:
598       size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin));
599       break;
600     case FAKESRC_SIZETYPE_NULL:
601     default:
602       size = 0; 
603       break;
604   }
605
606   return size;
607 }
608
609 static GstBuffer *
610 gst_fakesrc_create_buffer (GstFakeSrc *src)
611 {
612   GstBuffer *buf;
613   guint size;
614   gboolean dump = src->dump;
615
616   size = gst_fakesrc_get_size (src);
617   if (size == 0)
618     return gst_buffer_new();
619
620   switch (src->data) {
621     case FAKESRC_DATA_ALLOCATE:
622       buf = gst_fakesrc_alloc_buffer (src, size);
623       break;
624     case FAKESRC_DATA_SUBBUFFER:
625       /* see if we have a parent to subbuffer */
626       if (!src->parent) {
627         gst_fakesrc_alloc_parent (src);
628         g_assert (src->parent);
629       }
630       /* see if it's large enough */
631       if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
632          buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
633          src->parentoffset += size;
634       }
635       else {
636         /* the parent is useless now */
637         gst_buffer_unref (src->parent);
638         src->parent = NULL;
639         /* try again (this will allocate a new parent) */
640         return gst_fakesrc_create_buffer (src);
641       }
642       gst_fakesrc_prepare_buffer (src, buf);
643       break;
644     case FAKESRC_DATA_BUFFERPOOL:
645       buf = gst_buffer_new_from_pool (src->pool, 0, 0);
646       gst_fakesrc_prepare_buffer (src, buf);
647       break;
648     default:
649       g_warning ("fakesrc: dunno how to allocate buffers !");
650       buf = gst_buffer_new();
651       break;
652   }
653   if (dump) {
654     gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
655   }
656
657   return buf;
658 }
659
660 static GstBuffer *
661 gst_fakesrc_get(GstPad *pad)
662 {
663   GstFakeSrc *src;
664   GstBuffer *buf;
665
666   g_return_val_if_fail (pad != NULL, NULL);
667
668   src = GST_FAKESRC (gst_pad_get_parent (pad));
669
670   g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
671
672   if (src->need_flush) {
673     src->need_flush = FALSE;
674     return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
675   }
676
677   if (src->rt_num_buffers == 0) {
678     gst_element_set_eos (GST_ELEMENT (src));
679     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
680   }
681   else {
682     if (src->rt_num_buffers > 0)
683       src->rt_num_buffers--;
684   }
685
686   if (src->eos) {
687     GST_INFO (0, "fakesrc is setting eos on pad");
688     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
689   }
690
691   buf = gst_fakesrc_create_buffer (src);
692   GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
693
694   if (!src->silent) {
695     if (src->last_message)
696       g_free (src->last_message);
697
698     src->last_message = g_strdup_printf ("get      ******* (%s:%s)> (%d bytes, %llu) %p",
699                       GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
700
701     g_object_notify (G_OBJECT (src), "last_message");
702   }
703
704   GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "pre handoff emit");
705   g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
706                    buf, pad);
707   GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "post handoff emit");
708
709   return buf;
710 }
711
712 /**
713  * gst_fakesrc_loop:
714  * @element: the faksesrc to loop
715  * 
716  * generate an empty buffer and push it to the next element.
717  */
718 static void
719 gst_fakesrc_loop(GstElement *element)
720 {
721   GstFakeSrc *src;
722   GList *pads;
723
724   g_return_if_fail(element != NULL);
725   g_return_if_fail(GST_IS_FAKESRC(element));
726
727   src = GST_FAKESRC (element);
728
729   pads = gst_element_get_pad_list (element);
730
731   while (pads) {
732     GstPad *pad = GST_PAD (pads->data);
733     GstBuffer *buf;
734
735     if (src->rt_num_buffers == 0) {
736       src->eos = TRUE;
737     }
738     else {
739       if (src->rt_num_buffers > 0)
740         src->rt_num_buffers--;
741     }
742
743     if (src->eos) {
744       gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
745       return;
746     }
747
748     buf = gst_fakesrc_create_buffer (src);
749     GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
750
751     if (!src->silent) {
752       if (src->last_message)
753         g_free (src->last_message);
754
755       src->last_message = g_strdup_printf ("fakesrc:  loop    ******* (%s:%s)  > (%d bytes, %llu)",
756                       GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
757
758       g_object_notify (G_OBJECT (src), "last_message");
759     }
760
761     g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
762                        buf, pad);
763     gst_pad_push (pad, buf);
764
765     pads = g_list_next (pads);
766   }
767 }
768
769 static GstElementStateReturn
770 gst_fakesrc_change_state (GstElement *element)
771 {
772   GstFakeSrc *fakesrc;
773
774   g_return_val_if_fail (GST_IS_FAKESRC (element), GST_STATE_FAILURE);
775
776   fakesrc = GST_FAKESRC (element);
777
778   switch (GST_STATE_TRANSITION (element)) {
779     case GST_STATE_PAUSED_TO_READY:
780     case GST_STATE_NULL_TO_READY:
781       fakesrc->buffer_count = 0;
782       fakesrc->pattern_byte = 0x00;
783       fakesrc->need_flush = FALSE;
784       fakesrc->eos = FALSE;
785       fakesrc->rt_num_buffers = fakesrc->num_buffers;
786       break;
787     case GST_STATE_READY_TO_PAUSED:
788     case GST_STATE_PAUSED_TO_PLAYING:
789     case GST_STATE_PLAYING_TO_PAUSED:
790       break;
791     case GST_STATE_READY_TO_NULL:
792       if (fakesrc->parent) {
793         gst_buffer_unref (fakesrc->parent);
794         fakesrc->parent = NULL;
795       }
796       if (fakesrc->pool) {
797         gst_buffer_pool_unref (fakesrc->pool);
798         fakesrc->pool = NULL;
799       }
800       break;
801     default:
802       g_assert_not_reached ();
803       break;
804   }
805
806   if (GST_ELEMENT_CLASS (parent_class)->change_state)
807     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
808
809   return GST_STATE_SUCCESS;
810 }
811
812 gboolean
813 gst_fakesrc_factory_init (GstElementFactory *factory)
814 {
815   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (fakesrc_src_factory));
816
817   return TRUE;
818 }
819