e4d496e6ef27c2b501d6e1321f864e6326967541
[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_PADTEMPLATE_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,            "2", "Allocate data"},
103     { FAKESRC_DATA_SUBBUFFER,           "3", "Subbuffer data"},
104     {0, NULL, NULL},
105   };
106   if (!fakesrc_data_type) {
107     fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
108   }
109   return fakesrc_data_type;
110 }
111
112 #define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
113 static GType
114 gst_fakesrc_sizetype_get_type (void) 
115 {
116   static GType fakesrc_sizetype_type = 0;
117   static GEnumValue fakesrc_sizetype[] = {
118     { FAKESRC_SIZETYPE_NULL,            "1", "Send empty buffers"},
119     { FAKESRC_SIZETYPE_FIXED,           "2", "Fixed size buffers (sizemax sized)"},
120     { FAKESRC_SIZETYPE_RANDOM,          "3", "Random sized buffers (sizemin <= size <= sizemax)"},
121     {0, NULL, NULL},
122   };
123   if (!fakesrc_sizetype_type) {
124     fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
125   }
126   return fakesrc_sizetype_type;
127 }
128
129 #define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
130 static GType
131 gst_fakesrc_filltype_get_type (void) 
132 {
133   static GType fakesrc_filltype_type = 0;
134   static GEnumValue fakesrc_filltype[] = {
135     { FAKESRC_FILLTYPE_NOTHING,         "1", "Leave data as malloced"},
136     { FAKESRC_FILLTYPE_NULL,            "2", "Fill buffers with zeros"},
137     { FAKESRC_FILLTYPE_RANDOM,          "3", "Fill buffers with random crap"},
138     { FAKESRC_FILLTYPE_PATTERN,         "4", "Fill buffers with pattern 0x00 -> 0xff"},
139     { FAKESRC_FILLTYPE_PATTERN_CONT,    "5", "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
140     {0, NULL, NULL},
141   };
142   if (!fakesrc_filltype_type) {
143     fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
144   }
145   return fakesrc_filltype_type;
146 }
147
148 static void             gst_fakesrc_class_init          (GstFakeSrcClass *klass);
149 static void             gst_fakesrc_init                (GstFakeSrc *fakesrc);
150
151 static GstPad*          gst_fakesrc_request_new_pad     (GstElement *element, GstPadTemplate *templ);
152 static void             gst_fakesrc_update_functions    (GstFakeSrc *src);
153 static void             gst_fakesrc_set_property        (GObject *object, guint prop_id, 
154                                                          const GValue *value, GParamSpec *pspec);
155 static void             gst_fakesrc_get_property        (GObject *object, guint prop_id, 
156                                                          GValue *value, GParamSpec *pspec);
157
158 static GstElementStateReturn gst_fakesrc_change_state   (GstElement *element);
159
160 static GstBuffer*       gst_fakesrc_get                 (GstPad *pad);
161 static void             gst_fakesrc_loop                (GstElement *element);
162
163 static GstElementClass *parent_class = NULL;
164 static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
165
166 GType
167 gst_fakesrc_get_type (void) 
168 {
169   static GType fakesrc_type = 0;
170
171   if (!fakesrc_type) {
172     static const GTypeInfo fakesrc_info = {
173       sizeof(GstFakeSrcClass),
174       NULL,
175       NULL,
176       (GClassInitFunc)gst_fakesrc_class_init,
177       NULL,
178       NULL,
179       sizeof(GstFakeSrc),
180       0,
181       (GInstanceInitFunc)gst_fakesrc_init,
182     };
183     fakesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFakeSrc", &fakesrc_info, 0);
184   }
185   return fakesrc_type;
186 }
187
188 static void
189 gst_fakesrc_class_init (GstFakeSrcClass *klass) 
190 {
191   GObjectClass *gobject_class;
192   GstElementClass *gstelement_class;
193
194   gobject_class = (GObjectClass*)klass;
195   gstelement_class = (GstElementClass*)klass;
196
197   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
198
199   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
200     g_param_spec_int ("num_sources", "num_sources", "num_sources",
201                       1, G_MAXINT, 1, G_PARAM_READABLE));
202   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LOOP_BASED,
203     g_param_spec_boolean("loop_based","loop_based","loop_based",
204                          FALSE, G_PARAM_READWRITE)); /* CHECKME */
205   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT,
206     g_param_spec_enum("output","output","output",
207                       GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE)); /* CHECKME! */
208   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
209     g_param_spec_enum ("data", "data", "data",
210                        GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE)); 
211   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
212     g_param_spec_enum ("sizetype", "sizetype", "sizetype",
213                        GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE)); 
214   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
215     g_param_spec_int ("sizemin","sizemin","sizemin",
216                       0, G_MAXINT, 0, G_PARAM_READWRITE)); 
217   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
218     g_param_spec_int ("sizemax","sizemax","sizemax",
219                       0, G_MAXINT, 4096, G_PARAM_READWRITE)); 
220   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
221     g_param_spec_int ("parentsize","parentsize","parentsize",
222                       0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE)); 
223   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
224     g_param_spec_enum ("filltype", "filltype", "filltype",
225                        GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE)); 
226   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN,
227     g_param_spec_string("pattern","pattern","pattern",
228                         NULL, G_PARAM_READWRITE)); /* CHECKME */
229   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NUM_BUFFERS,
230     g_param_spec_int("num_buffers","num_buffers","num_buffers",
231                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); /* CHECKME */
232   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_EOS,
233     g_param_spec_boolean("eos","eos","eos",
234                          TRUE,G_PARAM_READWRITE)); /* CHECKME */
235   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
236     g_param_spec_string ("last_message", "last_message", "last_message",
237                          NULL, G_PARAM_READABLE)); 
238
239   gst_element_install_std_props (
240           GST_ELEMENT_CLASS (klass),
241           "silent", ARG_SILENT, G_PARAM_READWRITE,
242           "dump",   ARG_DUMP,   G_PARAM_READWRITE,
243           NULL);
244
245   gst_fakesrc_signals[SIGNAL_HANDOFF] =
246     g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
247                     G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
248                     g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
249                     G_TYPE_POINTER);
250
251   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
252   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
253
254   gstelement_class->request_new_pad =   GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
255   gstelement_class->change_state =      GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
256 }
257
258 static void 
259 gst_fakesrc_init (GstFakeSrc *fakesrc) 
260 {
261   GstPad *pad;
262
263   /* create our first output pad */
264   pad = gst_pad_new ("src", GST_PAD_SRC);
265   gst_element_add_pad (GST_ELEMENT (fakesrc), pad);
266
267   fakesrc->loop_based = FALSE;
268   gst_fakesrc_update_functions (fakesrc);
269
270   fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
271   fakesrc->num_buffers = -1;
272   fakesrc->rt_num_buffers = -1;
273   fakesrc->buffer_count = 0;
274   fakesrc->silent = FALSE;
275   fakesrc->dump = FALSE;
276   fakesrc->pattern_byte = 0x00;
277   fakesrc->need_flush = FALSE;
278   fakesrc->data = FAKESRC_DATA_ALLOCATE;
279   fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
280   fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
281   fakesrc->sizemin = 0;
282   fakesrc->sizemax = 4096;
283   fakesrc->parent = NULL;
284   fakesrc->parentsize = 4096 * 10;
285   fakesrc->last_message = NULL;
286 }
287
288 static GstPad*
289 gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
290 {
291   gchar *name;
292   GstPad *srcpad;
293   GstFakeSrc *fakesrc;
294
295   g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
296
297   if (templ->direction != GST_PAD_SRC) {
298     g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
299     return NULL;
300   }
301
302   fakesrc = GST_FAKESRC (element);
303
304   name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
305
306   srcpad = gst_pad_new_from_template (templ, name);
307   gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
308
309   g_free (name);
310
311   return srcpad;
312 }
313
314 static gboolean
315 gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
316 {
317   GstFakeSrc *src;
318
319   src = GST_FAKESRC (gst_pad_get_parent (pad));
320
321   switch (GST_EVENT_TYPE (event)) {
322     case GST_EVENT_SEEK:
323       src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
324       if (!GST_EVENT_SEEK_FLUSH (event)) {
325         gst_event_free (event);
326         break;
327       }
328       /* else we do a flush too */
329     case GST_EVENT_FLUSH:
330       src->need_flush = TRUE;
331       break;
332     default:
333       break;
334   }
335
336   return TRUE;
337 }
338
339 static void
340 gst_fakesrc_update_functions (GstFakeSrc *src)
341 {
342   GList *pads;
343
344   if (src->loop_based) {
345     gst_element_set_loop_function (GST_ELEMENT (src), GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
346   }
347   else {
348     gst_element_set_loop_function (GST_ELEMENT (src), NULL);
349   }
350
351   pads = GST_ELEMENT (src)->pads;
352   while (pads) {
353     GstPad *pad = GST_PAD (pads->data);
354
355     if (src->loop_based) {
356       gst_pad_set_get_function (pad, NULL);
357     }
358     else {
359       gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
360     }
361
362     gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
363     pads = g_list_next (pads);
364   }
365 }
366
367 static void
368 gst_fakesrc_alloc_parent (GstFakeSrc *src)
369 {
370   GstBuffer *buf;
371
372   buf = gst_buffer_new ();
373   GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
374   GST_BUFFER_SIZE (buf) = src->parentsize;
375
376   src->parent = buf;
377   src->parentoffset = 0;
378 }
379
380 static void
381 gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
382 {
383   GstFakeSrc *src;
384
385   /* it's not null if we got it, but it might not be ours */
386   src = GST_FAKESRC (object);
387    
388   switch (prop_id) {
389     case ARG_LOOP_BASED:
390       src->loop_based = g_value_get_boolean (value);
391       gst_fakesrc_update_functions (src);
392       break;
393     case ARG_OUTPUT:
394       g_warning ("not yet implemented");
395       break;
396     case ARG_DATA:
397       src->data = g_value_get_enum (value);
398       switch (src->data) {
399         case FAKESRC_DATA_ALLOCATE:
400           if (src->parent) {
401             gst_buffer_unref (src->parent);
402             src->parent = NULL;
403           }
404           break;
405         case FAKESRC_DATA_SUBBUFFER:
406           if (!src->parent)
407             gst_fakesrc_alloc_parent (src);
408         default:
409           break;
410       }
411       break;
412     case ARG_SIZETYPE:
413       src->sizetype = g_value_get_enum (value);
414       break;
415     case ARG_SIZEMIN:
416       src->sizemin = g_value_get_int (value);
417       break;
418     case ARG_SIZEMAX:
419       src->sizemax = g_value_get_int (value);
420       break;
421     case ARG_PARENTSIZE:
422       src->parentsize = g_value_get_int (value);
423       break;
424     case ARG_FILLTYPE:
425       src->filltype = g_value_get_enum (value);
426       break;
427     case ARG_PATTERN:
428       break;
429     case ARG_NUM_BUFFERS:
430       src->num_buffers = g_value_get_int (value);
431       break;
432     case ARG_EOS:
433       src->eos = g_value_get_boolean (value);
434       GST_INFO (0, "will EOS on next buffer");
435       break;
436     case ARG_SILENT:
437       src->silent = g_value_get_boolean (value);
438       break;
439     case ARG_DUMP:
440       src->dump = g_value_get_boolean (value);
441       break;
442     default:
443       break;
444   }
445 }
446
447 static void 
448 gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
449 {
450   GstFakeSrc *src;
451    
452   /* it's not null if we got it, but it might not be ours */
453   g_return_if_fail (GST_IS_FAKESRC (object));
454   
455   src = GST_FAKESRC (object);
456    
457   switch (prop_id) {
458     case ARG_NUM_SOURCES:
459       g_value_set_int (value, GST_ELEMENT (src)->numsrcpads);
460       break;
461     case ARG_LOOP_BASED:
462       g_value_set_boolean (value, src->loop_based);
463       break;
464     case ARG_OUTPUT:
465       g_value_set_enum (value, src->output);
466       break;
467     case ARG_DATA:
468       g_value_set_enum (value, src->data);
469       break;
470     case ARG_SIZETYPE:
471       g_value_set_enum (value, src->sizetype);
472       break;
473     case ARG_SIZEMIN:
474       g_value_set_int (value, src->sizemin);
475       break;
476     case ARG_SIZEMAX:
477       g_value_set_int (value, src->sizemax);
478       break;
479     case ARG_PARENTSIZE:
480       g_value_set_int (value, src->parentsize);
481       break;
482     case ARG_FILLTYPE:
483       g_value_set_enum (value, src->filltype);
484       break;
485     case ARG_PATTERN:
486       g_value_set_string (value, src->pattern);
487       break;
488     case ARG_NUM_BUFFERS:
489       g_value_set_int (value, src->num_buffers);
490       break;
491     case ARG_EOS:
492       g_value_set_boolean (value, src->eos);
493       break;
494     case ARG_SILENT:
495       g_value_set_boolean (value, src->silent);
496       break;
497     case ARG_DUMP:
498       g_value_set_boolean (value, src->dump);
499       break;
500     case ARG_LAST_MESSAGE:
501       g_value_set_string (value, src->last_message);
502       break;
503     default:
504       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
505       break;
506   }
507 }
508
509 static void
510 gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
511 {
512   if (GST_BUFFER_SIZE (buf) == 0) 
513     return;
514
515   switch (src->filltype) {
516     case FAKESRC_FILLTYPE_NULL:
517       memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
518       break;
519     case FAKESRC_FILLTYPE_RANDOM:
520     {
521       gint i;
522       guint8 *ptr = GST_BUFFER_DATA (buf);
523
524       for (i = GST_BUFFER_SIZE (buf); i; i--) {
525         *ptr++ = (gint8)((255.0)*rand()/(RAND_MAX));
526       }
527       break;
528     }
529     case FAKESRC_FILLTYPE_PATTERN:
530       src->pattern_byte = 0x00;
531     case FAKESRC_FILLTYPE_PATTERN_CONT:
532     {
533       gint i;
534       guint8 *ptr = GST_BUFFER_DATA (buf);
535
536       for (i = GST_BUFFER_SIZE (buf); i; i--) {
537         *ptr++ = src->pattern_byte++;
538       }
539       break;
540     }
541     case FAKESRC_FILLTYPE_NOTHING:
542     default:
543       break;
544   }
545 }
546
547 static GstBuffer*
548 gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
549 {
550   GstBuffer *buf;
551
552   buf = gst_buffer_new ();
553   GST_BUFFER_SIZE(buf) = size;
554
555   if (size != 0) { 
556     switch (src->filltype) {
557       case FAKESRC_FILLTYPE_NOTHING:
558         GST_BUFFER_DATA(buf) = g_malloc (size);
559         break;
560       case FAKESRC_FILLTYPE_NULL:
561         GST_BUFFER_DATA(buf) = g_malloc0 (size);
562         break;
563       case FAKESRC_FILLTYPE_RANDOM:
564       case FAKESRC_FILLTYPE_PATTERN:
565       case FAKESRC_FILLTYPE_PATTERN_CONT:
566       default:
567         GST_BUFFER_DATA(buf) = g_malloc (size);
568         gst_fakesrc_prepare_buffer (src, buf);
569         break;
570     }
571   }
572
573   return buf;
574 }
575
576 static guint
577 gst_fakesrc_get_size (GstFakeSrc *src)
578 {
579   guint size;
580
581   switch (src->sizetype) {
582     case FAKESRC_SIZETYPE_FIXED:
583       size = src->sizemax;
584       break;
585     case FAKESRC_SIZETYPE_RANDOM:
586       size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin));
587       break;
588     case FAKESRC_SIZETYPE_NULL:
589     default:
590       size = 0; 
591       break;
592   }
593
594   return size;
595 }
596
597 static GstBuffer *
598 gst_fakesrc_create_buffer (GstFakeSrc *src)
599 {
600   GstBuffer *buf;
601   guint size;
602   gboolean dump = src->dump;
603
604   size = gst_fakesrc_get_size (src);
605   if (size == 0)
606     return gst_buffer_new();
607
608   switch (src->data) {
609     case FAKESRC_DATA_ALLOCATE:
610       buf = gst_fakesrc_alloc_buffer (src, size);
611       break;
612     case FAKESRC_DATA_SUBBUFFER:
613       /* see if we have a parent to subbuffer */
614       if (!src->parent) {
615         gst_fakesrc_alloc_parent (src);
616         g_assert (src->parent);
617       }
618       /* see if it's large enough */
619       if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
620          buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
621          src->parentoffset += size;
622       }
623       else {
624         /* the parent is useless now */
625         gst_buffer_unref (src->parent);
626         src->parent = NULL;
627         /* try again (this will allocate a new parent) */
628         return gst_fakesrc_create_buffer (src);
629       }
630       gst_fakesrc_prepare_buffer (src, buf);
631       break;
632     default:
633       g_warning ("fakesrc: dunno how to allocate buffers !");
634       buf = gst_buffer_new();
635       break;
636   }
637   if (dump) {
638     gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
639   }
640
641   return buf;
642 }
643
644 static GstBuffer *
645 gst_fakesrc_get(GstPad *pad)
646 {
647   GstFakeSrc *src;
648   GstBuffer *buf;
649
650   g_return_val_if_fail (pad != NULL, NULL);
651
652   src = GST_FAKESRC (gst_pad_get_parent (pad));
653
654   g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
655
656   if (src->need_flush) {
657     src->need_flush = FALSE;
658     return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
659   }
660
661   if (src->rt_num_buffers == 0) {
662     gst_element_set_eos (GST_ELEMENT (src));
663     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
664   }
665   else {
666     if (src->rt_num_buffers > 0)
667       src->rt_num_buffers--;
668   }
669
670   if (src->eos) {
671     GST_INFO (0, "fakesrc is setting eos on pad");
672     return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
673   }
674
675   buf = gst_fakesrc_create_buffer (src);
676   GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
677
678   if (!src->silent) {
679     if (src->last_message)
680       g_free (src->last_message);
681
682     src->last_message = g_strdup_printf ("get      ******* (%s:%s)> (%d bytes, %llu)",
683                       GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
684
685     g_object_notify (G_OBJECT (src), "last_message");
686   }
687
688   GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "pre handoff emit\n");
689   g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
690                    buf, pad);
691   GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "post handoff emit\n");
692
693   return buf;
694 }
695
696 /**
697  * gst_fakesrc_loop:
698  * @element: the faksesrc to loop
699  * 
700  * generate an empty buffer and push it to the next element.
701  */
702 static void
703 gst_fakesrc_loop(GstElement *element)
704 {
705   GstFakeSrc *src;
706   GList *pads;
707
708   g_return_if_fail(element != NULL);
709   g_return_if_fail(GST_IS_FAKESRC(element));
710
711   src = GST_FAKESRC (element);
712
713   pads = gst_element_get_pad_list (element);
714
715   while (pads) {
716     GstPad *pad = GST_PAD (pads->data);
717     GstBuffer *buf;
718
719     if (src->rt_num_buffers == 0) {
720       src->eos = TRUE;
721     }
722     else {
723       if (src->rt_num_buffers > 0)
724         src->rt_num_buffers--;
725     }
726
727     if (src->eos) {
728       gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
729       return;
730     }
731
732     buf = gst_fakesrc_create_buffer (src);
733     GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
734
735     if (!src->silent) {
736       if (src->last_message)
737         g_free (src->last_message);
738
739       src->last_message = g_strdup_printf ("fakesrc:  loop    ******* (%s:%s)  > (%d bytes, %llu)",
740                       GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
741
742       g_object_notify (G_OBJECT (src), "last_message");
743     }
744
745     g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
746                        buf, pad);
747     gst_pad_push (pad, buf);
748
749     pads = g_list_next (pads);
750   }
751 }
752
753 static GstElementStateReturn
754 gst_fakesrc_change_state (GstElement *element)
755 {
756   GstFakeSrc *fakesrc;
757
758   g_return_val_if_fail (GST_IS_FAKESRC (element), GST_STATE_FAILURE);
759
760   fakesrc = GST_FAKESRC (element);
761
762   switch (GST_STATE_TRANSITION (element)) {
763     case GST_STATE_PAUSED_TO_READY:
764     case GST_STATE_NULL_TO_READY:
765       fakesrc->buffer_count = 0;
766       fakesrc->pattern_byte = 0x00;
767       fakesrc->need_flush = FALSE;
768       fakesrc->eos = FALSE;
769       fakesrc->rt_num_buffers = fakesrc->num_buffers;
770       if (fakesrc->parent) {
771         gst_buffer_unref (fakesrc->parent);
772         fakesrc->parent = NULL;
773       }
774       break;
775     case GST_STATE_READY_TO_PAUSED:
776     case GST_STATE_PAUSED_TO_PLAYING:
777     case GST_STATE_PLAYING_TO_PAUSED:
778     case GST_STATE_READY_TO_NULL:
779       break;
780     default:
781       g_assert_not_reached ();
782       break;
783   }
784
785   if (GST_ELEMENT_CLASS (parent_class)->change_state)
786     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
787
788   return GST_STATE_SUCCESS;
789 }
790
791 gboolean
792 gst_fakesrc_factory_init (GstElementFactory *factory)
793 {
794   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (fakesrc_src_factory));
795
796   return TRUE;
797 }
798