Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstaudiosrc.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstaudiosrc.c: simple audio src base class
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  * SECTION:gstaudiosrc
25  * @short_description: Simple base class for audio sources
26  * @see_also: #GstBaseAudioSrc, #GstRingBuffer, #GstAudioSrc.
27  *
28  * This is the most simple base class for audio sources that only requires
29  * subclasses to implement a set of simple functions:
30  *
31  * <variablelist>
32  *   <varlistentry>
33  *     <term>open()</term>
34  *     <listitem><para>Open the device.</para></listitem>
35  *   </varlistentry>
36  *   <varlistentry>
37  *     <term>prepare()</term>
38  *     <listitem><para>Configure the device with the specified format.</para></listitem>
39  *   </varlistentry>
40  *   <varlistentry>
41  *     <term>read()</term>
42  *     <listitem><para>Read samples from the device.</para></listitem>
43  *   </varlistentry>
44  *   <varlistentry>
45  *     <term>reset()</term>
46  *     <listitem><para>Unblock reads and flush the device.</para></listitem>
47  *   </varlistentry>
48  *   <varlistentry>
49  *     <term>delay()</term>
50  *     <listitem><para>Get the number of samples in the device but not yet read.
51  *     </para></listitem>
52  *   </varlistentry>
53  *   <varlistentry>
54  *     <term>unprepare()</term>
55  *     <listitem><para>Undo operations done by prepare.</para></listitem>
56  *   </varlistentry>
57  *   <varlistentry>
58  *     <term>close()</term>
59  *     <listitem><para>Close the device.</para></listitem>
60  *   </varlistentry>
61  * </variablelist>
62  *
63  * All scheduling of samples and timestamps is done in this base class
64  * together with #GstBaseAudioSrc using a default implementation of a
65  * #GstRingBuffer that uses threads.
66  *
67  * Last reviewed on 2006-09-27 (0.10.12)
68  */
69
70 #include <string.h>
71
72 #include "gstaudiosrc.h"
73
74 GST_DEBUG_CATEGORY_STATIC (gst_audio_src_debug);
75 #define GST_CAT_DEFAULT gst_audio_src_debug
76
77 #define GST_TYPE_AUDIORING_BUFFER        \
78         (gst_audioringbuffer_get_type())
79 #define GST_AUDIORING_BUFFER(obj)        \
80         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer))
81 #define GST_AUDIORING_BUFFER_CLASS(klass) \
82         (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass))
83 #define GST_AUDIORING_BUFFER_GET_CLASS(obj) \
84         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass))
85 #define GST_IS_AUDIORING_BUFFER(obj)     \
86         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER))
87 #define GST_IS_AUDIORING_BUFFER_CLASS(klass)\
88         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER))
89
90 typedef struct _GstAudioRingBuffer GstAudioRingBuffer;
91 typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass;
92
93 #define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond)
94 #define GST_AUDIORING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
95 #define GST_AUDIORING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf)))
96 #define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf)))
97
98 struct _GstAudioRingBuffer
99 {
100   GstRingBuffer object;
101
102   gboolean running;
103   gint queuedseg;
104
105   GCond *cond;
106 };
107
108 struct _GstAudioRingBufferClass
109 {
110   GstRingBufferClass parent_class;
111 };
112
113 static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass);
114 static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
115     GstAudioRingBufferClass * klass);
116 static void gst_audioringbuffer_dispose (GObject * object);
117 static void gst_audioringbuffer_finalize (GObject * object);
118
119 static GstRingBufferClass *ring_parent_class = NULL;
120
121 static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf);
122 static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf);
123 static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
124     GstRingBufferSpec * spec);
125 static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
126 static gboolean gst_audioringbuffer_start (GstRingBuffer * buf);
127 static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
128 static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
129
130 /* ringbuffer abstract base class */
131 static GType
132 gst_audioringbuffer_get_type (void)
133 {
134   static GType ringbuffer_type = 0;
135
136   if (!ringbuffer_type) {
137     static const GTypeInfo ringbuffer_info = {
138       sizeof (GstAudioRingBufferClass),
139       NULL,
140       NULL,
141       (GClassInitFunc) gst_audioringbuffer_class_init,
142       NULL,
143       NULL,
144       sizeof (GstAudioRingBuffer),
145       0,
146       (GInstanceInitFunc) gst_audioringbuffer_init,
147       NULL
148     };
149
150     ringbuffer_type =
151         g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSrcRingBuffer",
152         &ringbuffer_info, 0);
153   }
154   return ringbuffer_type;
155 }
156
157 static void
158 gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass)
159 {
160   GObjectClass *gobject_class;
161   GstRingBufferClass *gstringbuffer_class;
162
163   gobject_class = (GObjectClass *) klass;
164   gstringbuffer_class = (GstRingBufferClass *) klass;
165
166   ring_parent_class = g_type_class_peek_parent (klass);
167
168   gobject_class->dispose = gst_audioringbuffer_dispose;
169   gobject_class->finalize = gst_audioringbuffer_finalize;
170
171   gstringbuffer_class->open_device =
172       GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device);
173   gstringbuffer_class->close_device =
174       GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device);
175   gstringbuffer_class->acquire =
176       GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
177   gstringbuffer_class->release =
178       GST_DEBUG_FUNCPTR (gst_audioringbuffer_release);
179   gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
180   gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
181   gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
182
183   gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
184 }
185
186 typedef guint (*ReadFunc) (GstAudioSrc * src, gpointer data, guint length);
187
188 /* this internal thread does nothing else but read samples from the audio device.
189  * It will read each segment in the ringbuffer and will update the play
190  * pointer. 
191  * The start/stop methods control the thread.
192  */
193 static void
194 audioringbuffer_thread_func (GstRingBuffer * buf)
195 {
196   GstAudioSrc *src;
197   GstAudioSrcClass *csrc;
198   GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER (buf);
199   ReadFunc readfunc;
200   GstMessage *message;
201   GValue val = { 0 };
202
203   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
204   csrc = GST_AUDIO_SRC_GET_CLASS (src);
205
206   GST_DEBUG_OBJECT (src, "enter thread");
207
208   readfunc = csrc->read;
209   if (readfunc == NULL)
210     goto no_function;
211
212   /* FIXME: maybe we should at least use a custom pointer type here? */
213   g_value_init (&val, G_TYPE_POINTER);
214   g_value_set_pointer (&val, src->thread);
215   message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
216       GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (src));
217   gst_message_set_stream_status_object (message, &val);
218   GST_DEBUG_OBJECT (src, "posting ENTER stream status");
219   gst_element_post_message (GST_ELEMENT_CAST (src), message);
220
221   while (TRUE) {
222     gint left, len;
223     guint8 *readptr;
224     gint readseg;
225
226     if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
227       gint read;
228
229       left = len;
230       do {
231         read = readfunc (src, readptr, left);
232         GST_LOG_OBJECT (src, "transfered %d bytes of %d to segment %d", read,
233             left, readseg);
234         if (read < 0 || read > left) {
235           GST_WARNING_OBJECT (src,
236               "error reading data %d (reason: %s), skipping segment", read,
237               g_strerror (errno));
238           break;
239         }
240         left -= read;
241         readptr += read;
242       } while (left > 0);
243
244       /* we read one segment */
245       gst_ring_buffer_advance (buf, 1);
246     } else {
247       GST_OBJECT_LOCK (abuf);
248       if (!abuf->running)
249         goto stop_running;
250       GST_DEBUG_OBJECT (src, "signal wait");
251       GST_AUDIORING_BUFFER_SIGNAL (buf);
252       GST_DEBUG_OBJECT (src, "wait for action");
253       GST_AUDIORING_BUFFER_WAIT (buf);
254       GST_DEBUG_OBJECT (src, "got signal");
255       if (!abuf->running)
256         goto stop_running;
257       GST_DEBUG_OBJECT (src, "continue running");
258       GST_OBJECT_UNLOCK (abuf);
259     }
260   }
261
262   /* Will never be reached */
263   g_assert_not_reached ();
264   return;
265
266   /* ERROR */
267 no_function:
268   {
269     GST_DEBUG ("no write function, exit thread");
270     return;
271   }
272 stop_running:
273   {
274     GST_OBJECT_UNLOCK (abuf);
275     GST_DEBUG ("stop running, exit thread");
276     message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
277         GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (src));
278     gst_message_set_stream_status_object (message, &val);
279     GST_DEBUG_OBJECT (src, "posting LEAVE stream status");
280     gst_element_post_message (GST_ELEMENT_CAST (src), message);
281     return;
282   }
283 }
284
285 static void
286 gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
287     GstAudioRingBufferClass * g_class)
288 {
289   ringbuffer->running = FALSE;
290   ringbuffer->queuedseg = 0;
291
292   ringbuffer->cond = g_cond_new ();
293 }
294
295 static void
296 gst_audioringbuffer_dispose (GObject * object)
297 {
298   GstAudioRingBuffer *ringbuffer = GST_AUDIORING_BUFFER (object);
299
300   if (ringbuffer->cond) {
301     g_cond_free (ringbuffer->cond);
302     ringbuffer->cond = NULL;
303   }
304
305   G_OBJECT_CLASS (ring_parent_class)->dispose (object);
306 }
307
308 static void
309 gst_audioringbuffer_finalize (GObject * object)
310 {
311   G_OBJECT_CLASS (ring_parent_class)->finalize (object);
312 }
313
314 static gboolean
315 gst_audioringbuffer_open_device (GstRingBuffer * buf)
316 {
317   GstAudioSrc *src;
318   GstAudioSrcClass *csrc;
319   gboolean result = TRUE;
320
321   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
322   csrc = GST_AUDIO_SRC_GET_CLASS (src);
323
324   if (csrc->open)
325     result = csrc->open (src);
326
327   if (!result)
328     goto could_not_open;
329
330   return result;
331
332 could_not_open:
333   {
334     return FALSE;
335   }
336 }
337
338 static gboolean
339 gst_audioringbuffer_close_device (GstRingBuffer * buf)
340 {
341   GstAudioSrc *src;
342   GstAudioSrcClass *csrc;
343   gboolean result = TRUE;
344
345   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
346   csrc = GST_AUDIO_SRC_GET_CLASS (src);
347
348   if (csrc->close)
349     result = csrc->close (src);
350
351   if (!result)
352     goto could_not_open;
353
354   return result;
355
356 could_not_open:
357   {
358     return FALSE;
359   }
360 }
361
362 static gboolean
363 gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
364 {
365   GstAudioSrc *src;
366   GstAudioSrcClass *csrc;
367   GstAudioRingBuffer *abuf;
368   gboolean result = FALSE;
369
370   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
371   csrc = GST_AUDIO_SRC_GET_CLASS (src);
372
373   if (csrc->prepare)
374     result = csrc->prepare (src, spec);
375
376   if (!result)
377     goto could_not_open;
378
379   buf->size = spec->segtotal * spec->segsize;
380   buf->memory = g_malloc0 (buf->size);
381
382   abuf = GST_AUDIORING_BUFFER (buf);
383   abuf->running = TRUE;
384
385   src->thread =
386       g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
387       NULL);
388   GST_AUDIORING_BUFFER_WAIT (buf);
389
390   return result;
391
392 could_not_open:
393   {
394     return FALSE;
395   }
396 }
397
398 /* function is called with LOCK */
399 static gboolean
400 gst_audioringbuffer_release (GstRingBuffer * buf)
401 {
402   GstAudioSrc *src;
403   GstAudioSrcClass *csrc;
404   GstAudioRingBuffer *abuf;
405   gboolean result = FALSE;
406
407   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
408   csrc = GST_AUDIO_SRC_GET_CLASS (src);
409   abuf = GST_AUDIORING_BUFFER (buf);
410
411   abuf->running = FALSE;
412   GST_AUDIORING_BUFFER_SIGNAL (buf);
413   GST_OBJECT_UNLOCK (buf);
414
415   /* join the thread */
416   g_thread_join (src->thread);
417
418   GST_OBJECT_LOCK (buf);
419
420   /* free the buffer */
421   g_free (buf->memory);
422   buf->memory = NULL;
423
424   if (csrc->unprepare)
425     result = csrc->unprepare (src);
426
427   return result;
428 }
429
430 static gboolean
431 gst_audioringbuffer_start (GstRingBuffer * buf)
432 {
433   GST_DEBUG ("start, sending signal");
434   GST_AUDIORING_BUFFER_SIGNAL (buf);
435
436   return TRUE;
437 }
438
439 static gboolean
440 gst_audioringbuffer_stop (GstRingBuffer * buf)
441 {
442   GstAudioSrc *src;
443   GstAudioSrcClass *csrc;
444
445   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
446   csrc = GST_AUDIO_SRC_GET_CLASS (src);
447
448   /* unblock any pending writes to the audio device */
449   if (csrc->reset) {
450     GST_DEBUG ("reset...");
451     csrc->reset (src);
452     GST_DEBUG ("reset done");
453   }
454 #if 0
455   GST_DEBUG ("stop, waiting...");
456   GST_AUDIORING_BUFFER_WAIT (buf);
457   GST_DEBUG ("stoped");
458 #endif
459
460   return TRUE;
461 }
462
463 static guint
464 gst_audioringbuffer_delay (GstRingBuffer * buf)
465 {
466   GstAudioSrc *src;
467   GstAudioSrcClass *csrc;
468   guint res = 0;
469
470   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
471   csrc = GST_AUDIO_SRC_GET_CLASS (src);
472
473   if (csrc->delay)
474     res = csrc->delay (src);
475
476   return res;
477 }
478
479 /* AudioSrc signals and args */
480 enum
481 {
482   /* FILL ME */
483   LAST_SIGNAL
484 };
485
486 enum
487 {
488   ARG_0,
489 };
490
491 #define _do_init \
492     GST_DEBUG_CATEGORY_INIT (gst_audio_src_debug, "audiosrc", 0, "audiosrc element");
493 #define gst_audio_src_parent_class parent_class
494 G_DEFINE_TYPE_WITH_CODE (GstAudioSrc, gst_audio_src,
495     GST_TYPE_BASE_AUDIO_SRC, _do_init);
496
497 static GstRingBuffer *gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src);
498
499 static void
500 gst_audio_src_class_init (GstAudioSrcClass * klass)
501 {
502   GstBaseAudioSrcClass *gstbaseaudiosrc_class;
503
504   gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
505
506   gstbaseaudiosrc_class->create_ringbuffer =
507       GST_DEBUG_FUNCPTR (gst_audio_src_create_ringbuffer);
508
509   g_type_class_ref (GST_TYPE_AUDIORING_BUFFER);
510 }
511
512 static void
513 gst_audio_src_init (GstAudioSrc * audiosrc)
514 {
515 }
516
517 static GstRingBuffer *
518 gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
519 {
520   GstRingBuffer *buffer;
521
522   GST_DEBUG ("creating ringbuffer");
523   buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL);
524   GST_DEBUG ("created ringbuffer @%p", buffer);
525
526   return buffer;
527 }