audio: rename internal audio ringbuffer
[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_AUDIO_SRC_RING_BUFFER        \
78         (gst_audio_src_ring_buffer_get_type())
79 #define GST_AUDIO_SRC_RING_BUFFER(obj)        \
80         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_SRC_RING_BUFFER,GstAudioSrcRingBuffer))
81 #define GST_AUDIO_SRC_RING_BUFFER_CLASS(klass) \
82         (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_SRC_RING_BUFFER,GstAudioSrcRingBufferClass))
83 #define GST_AUDIO_SRC_RING_BUFFER_GET_CLASS(obj) \
84         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIO_SRC_RING_BUFFER, GstAudioSrcRingBufferClass))
85 #define GST_IS_AUDIO_SRC_RING_BUFFER(obj)     \
86         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_SRC_RING_BUFFER))
87 #define GST_IS_AUDIO_SRC_RING_BUFFER_CLASS(klass)\
88         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_SRC_RING_BUFFER))
89
90 typedef struct _GstAudioSrcRingBuffer GstAudioSrcRingBuffer;
91 typedef struct _GstAudioSrcRingBufferClass GstAudioSrcRingBufferClass;
92
93 #define GST_AUDIO_SRC_RING_BUFFER_GET_COND(buf) (((GstAudioSrcRingBuffer *)buf)->cond)
94 #define GST_AUDIO_SRC_RING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIO_SRC_RING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
95 #define GST_AUDIO_SRC_RING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIO_SRC_RING_BUFFER_GET_COND (buf)))
96 #define GST_AUDIO_SRC_RING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIO_SRC_RING_BUFFER_GET_COND (buf)))
97
98 struct _GstAudioSrcRingBuffer
99 {
100   GstRingBuffer object;
101
102   gboolean running;
103   gint queuedseg;
104
105   GCond *cond;
106 };
107
108 struct _GstAudioSrcRingBufferClass
109 {
110   GstRingBufferClass parent_class;
111 };
112
113 static void gst_audio_src_ring_buffer_class_init (GstAudioSrcRingBufferClass *
114     klass);
115 static void gst_audio_src_ring_buffer_init (GstAudioSrcRingBuffer * ringbuffer,
116     GstAudioSrcRingBufferClass * klass);
117 static void gst_audio_src_ring_buffer_dispose (GObject * object);
118 static void gst_audio_src_ring_buffer_finalize (GObject * object);
119
120 static GstRingBufferClass *ring_parent_class = NULL;
121
122 static gboolean gst_audio_src_ring_buffer_open_device (GstRingBuffer * buf);
123 static gboolean gst_audio_src_ring_buffer_close_device (GstRingBuffer * buf);
124 static gboolean gst_audio_src_ring_buffer_acquire (GstRingBuffer * buf,
125     GstRingBufferSpec * spec);
126 static gboolean gst_audio_src_ring_buffer_release (GstRingBuffer * buf);
127 static gboolean gst_audio_src_ring_buffer_start (GstRingBuffer * buf);
128 static gboolean gst_audio_src_ring_buffer_stop (GstRingBuffer * buf);
129 static guint gst_audio_src_ring_buffer_delay (GstRingBuffer * buf);
130
131 /* ringbuffer abstract base class */
132 static GType
133 gst_audio_src_ring_buffer_get_type (void)
134 {
135   static GType ringbuffer_type = 0;
136
137   if (!ringbuffer_type) {
138     static const GTypeInfo ringbuffer_info = {
139       sizeof (GstAudioSrcRingBufferClass),
140       NULL,
141       NULL,
142       (GClassInitFunc) gst_audio_src_ring_buffer_class_init,
143       NULL,
144       NULL,
145       sizeof (GstAudioSrcRingBuffer),
146       0,
147       (GInstanceInitFunc) gst_audio_src_ring_buffer_init,
148       NULL
149     };
150
151     ringbuffer_type =
152         g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSrcRingBuffer",
153         &ringbuffer_info, 0);
154   }
155   return ringbuffer_type;
156 }
157
158 static void
159 gst_audio_src_ring_buffer_class_init (GstAudioSrcRingBufferClass * klass)
160 {
161   GObjectClass *gobject_class;
162   GstRingBufferClass *gstringbuffer_class;
163
164   gobject_class = (GObjectClass *) klass;
165   gstringbuffer_class = (GstRingBufferClass *) klass;
166
167   ring_parent_class = g_type_class_peek_parent (klass);
168
169   gobject_class->dispose = gst_audio_src_ring_buffer_dispose;
170   gobject_class->finalize = gst_audio_src_ring_buffer_finalize;
171
172   gstringbuffer_class->open_device =
173       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_open_device);
174   gstringbuffer_class->close_device =
175       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_close_device);
176   gstringbuffer_class->acquire =
177       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_acquire);
178   gstringbuffer_class->release =
179       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_release);
180   gstringbuffer_class->start =
181       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_start);
182   gstringbuffer_class->resume =
183       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_start);
184   gstringbuffer_class->stop =
185       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_stop);
186
187   gstringbuffer_class->delay =
188       GST_DEBUG_FUNCPTR (gst_audio_src_ring_buffer_delay);
189 }
190
191 typedef guint (*ReadFunc) (GstAudioSrc * src, gpointer data, guint length);
192
193 /* this internal thread does nothing else but read samples from the audio device.
194  * It will read each segment in the ringbuffer and will update the play
195  * pointer. 
196  * The start/stop methods control the thread.
197  */
198 static void
199 audioringbuffer_thread_func (GstRingBuffer * buf)
200 {
201   GstAudioSrc *src;
202   GstAudioSrcClass *csrc;
203   GstAudioSrcRingBuffer *abuf = GST_AUDIO_SRC_RING_BUFFER (buf);
204   ReadFunc readfunc;
205   GstMessage *message;
206   GValue val = { 0 };
207
208   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
209   csrc = GST_AUDIO_SRC_GET_CLASS (src);
210
211   GST_DEBUG_OBJECT (src, "enter thread");
212
213   readfunc = csrc->read;
214   if (readfunc == NULL)
215     goto no_function;
216
217   /* FIXME: maybe we should at least use a custom pointer type here? */
218   g_value_init (&val, G_TYPE_POINTER);
219   g_value_set_pointer (&val, src->thread);
220   message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
221       GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (src));
222   gst_message_set_stream_status_object (message, &val);
223   GST_DEBUG_OBJECT (src, "posting ENTER stream status");
224   gst_element_post_message (GST_ELEMENT_CAST (src), message);
225
226   while (TRUE) {
227     gint left, len;
228     guint8 *readptr;
229     gint readseg;
230
231     if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
232       gint read;
233
234       left = len;
235       do {
236         read = readfunc (src, readptr, left);
237         GST_LOG_OBJECT (src, "transfered %d bytes of %d to segment %d", read,
238             left, readseg);
239         if (read < 0 || read > left) {
240           GST_WARNING_OBJECT (src,
241               "error reading data %d (reason: %s), skipping segment", read,
242               g_strerror (errno));
243           break;
244         }
245         left -= read;
246         readptr += read;
247       } while (left > 0);
248
249       /* we read one segment */
250       gst_ring_buffer_advance (buf, 1);
251     } else {
252       GST_OBJECT_LOCK (abuf);
253       if (!abuf->running)
254         goto stop_running;
255       if (G_UNLIKELY (g_atomic_int_get (&buf->state) ==
256               GST_RING_BUFFER_STATE_STARTED)) {
257         GST_OBJECT_UNLOCK (abuf);
258         continue;
259       }
260       GST_DEBUG_OBJECT (src, "signal wait");
261       GST_AUDIO_SRC_RING_BUFFER_SIGNAL (buf);
262       GST_DEBUG_OBJECT (src, "wait for action");
263       GST_AUDIO_SRC_RING_BUFFER_WAIT (buf);
264       GST_DEBUG_OBJECT (src, "got signal");
265       if (!abuf->running)
266         goto stop_running;
267       GST_DEBUG_OBJECT (src, "continue running");
268       GST_OBJECT_UNLOCK (abuf);
269     }
270   }
271
272   /* Will never be reached */
273   g_assert_not_reached ();
274   return;
275
276   /* ERROR */
277 no_function:
278   {
279     GST_DEBUG ("no write function, exit thread");
280     return;
281   }
282 stop_running:
283   {
284     GST_OBJECT_UNLOCK (abuf);
285     GST_DEBUG ("stop running, exit thread");
286     message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
287         GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (src));
288     gst_message_set_stream_status_object (message, &val);
289     GST_DEBUG_OBJECT (src, "posting LEAVE stream status");
290     gst_element_post_message (GST_ELEMENT_CAST (src), message);
291     return;
292   }
293 }
294
295 static void
296 gst_audio_src_ring_buffer_init (GstAudioSrcRingBuffer * ringbuffer,
297     GstAudioSrcRingBufferClass * g_class)
298 {
299   ringbuffer->running = FALSE;
300   ringbuffer->queuedseg = 0;
301
302   ringbuffer->cond = g_cond_new ();
303 }
304
305 static void
306 gst_audio_src_ring_buffer_dispose (GObject * object)
307 {
308   GstAudioSrcRingBuffer *ringbuffer = GST_AUDIO_SRC_RING_BUFFER (object);
309
310   if (ringbuffer->cond) {
311     g_cond_free (ringbuffer->cond);
312     ringbuffer->cond = NULL;
313   }
314
315   G_OBJECT_CLASS (ring_parent_class)->dispose (object);
316 }
317
318 static void
319 gst_audio_src_ring_buffer_finalize (GObject * object)
320 {
321   G_OBJECT_CLASS (ring_parent_class)->finalize (object);
322 }
323
324 static gboolean
325 gst_audio_src_ring_buffer_open_device (GstRingBuffer * buf)
326 {
327   GstAudioSrc *src;
328   GstAudioSrcClass *csrc;
329   gboolean result = TRUE;
330
331   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
332   csrc = GST_AUDIO_SRC_GET_CLASS (src);
333
334   if (csrc->open)
335     result = csrc->open (src);
336
337   if (!result)
338     goto could_not_open;
339
340   return result;
341
342 could_not_open:
343   {
344     return FALSE;
345   }
346 }
347
348 static gboolean
349 gst_audio_src_ring_buffer_close_device (GstRingBuffer * buf)
350 {
351   GstAudioSrc *src;
352   GstAudioSrcClass *csrc;
353   gboolean result = TRUE;
354
355   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
356   csrc = GST_AUDIO_SRC_GET_CLASS (src);
357
358   if (csrc->close)
359     result = csrc->close (src);
360
361   if (!result)
362     goto could_not_open;
363
364   return result;
365
366 could_not_open:
367   {
368     return FALSE;
369   }
370 }
371
372 static gboolean
373 gst_audio_src_ring_buffer_acquire (GstRingBuffer * buf,
374     GstRingBufferSpec * spec)
375 {
376   GstAudioSrc *src;
377   GstAudioSrcClass *csrc;
378   GstAudioSrcRingBuffer *abuf;
379   gboolean result = FALSE;
380
381   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
382   csrc = GST_AUDIO_SRC_GET_CLASS (src);
383
384   if (csrc->prepare)
385     result = csrc->prepare (src, spec);
386
387   if (!result)
388     goto could_not_open;
389
390   buf->size = spec->segtotal * spec->segsize;
391   buf->memory = g_malloc0 (buf->size);
392
393   abuf = GST_AUDIO_SRC_RING_BUFFER (buf);
394   abuf->running = TRUE;
395
396   src->thread =
397       g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
398       NULL);
399   GST_AUDIO_SRC_RING_BUFFER_WAIT (buf);
400
401   return result;
402
403 could_not_open:
404   {
405     return FALSE;
406   }
407 }
408
409 /* function is called with LOCK */
410 static gboolean
411 gst_audio_src_ring_buffer_release (GstRingBuffer * buf)
412 {
413   GstAudioSrc *src;
414   GstAudioSrcClass *csrc;
415   GstAudioSrcRingBuffer *abuf;
416   gboolean result = FALSE;
417
418   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
419   csrc = GST_AUDIO_SRC_GET_CLASS (src);
420   abuf = GST_AUDIO_SRC_RING_BUFFER (buf);
421
422   abuf->running = FALSE;
423   GST_AUDIO_SRC_RING_BUFFER_SIGNAL (buf);
424   GST_OBJECT_UNLOCK (buf);
425
426   /* join the thread */
427   g_thread_join (src->thread);
428
429   GST_OBJECT_LOCK (buf);
430
431   /* free the buffer */
432   g_free (buf->memory);
433   buf->memory = NULL;
434
435   if (csrc->unprepare)
436     result = csrc->unprepare (src);
437
438   return result;
439 }
440
441 static gboolean
442 gst_audio_src_ring_buffer_start (GstRingBuffer * buf)
443 {
444   GST_DEBUG ("start, sending signal");
445   GST_AUDIO_SRC_RING_BUFFER_SIGNAL (buf);
446
447   return TRUE;
448 }
449
450 static gboolean
451 gst_audio_src_ring_buffer_stop (GstRingBuffer * buf)
452 {
453   GstAudioSrc *src;
454   GstAudioSrcClass *csrc;
455
456   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
457   csrc = GST_AUDIO_SRC_GET_CLASS (src);
458
459   /* unblock any pending writes to the audio device */
460   if (csrc->reset) {
461     GST_DEBUG ("reset...");
462     csrc->reset (src);
463     GST_DEBUG ("reset done");
464   }
465 #if 0
466   GST_DEBUG ("stop, waiting...");
467   GST_AUDIO_SRC_RING_BUFFER_WAIT (buf);
468   GST_DEBUG ("stoped");
469 #endif
470
471   return TRUE;
472 }
473
474 static guint
475 gst_audio_src_ring_buffer_delay (GstRingBuffer * buf)
476 {
477   GstAudioSrc *src;
478   GstAudioSrcClass *csrc;
479   guint res = 0;
480
481   src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
482   csrc = GST_AUDIO_SRC_GET_CLASS (src);
483
484   if (csrc->delay)
485     res = csrc->delay (src);
486
487   return res;
488 }
489
490 /* AudioSrc signals and args */
491 enum
492 {
493   /* FILL ME */
494   LAST_SIGNAL
495 };
496
497 enum
498 {
499   ARG_0,
500 };
501
502 #define _do_init \
503     GST_DEBUG_CATEGORY_INIT (gst_audio_src_debug, "audiosrc", 0, "audiosrc element");
504 #define gst_audio_src_parent_class parent_class
505 G_DEFINE_TYPE_WITH_CODE (GstAudioSrc, gst_audio_src,
506     GST_TYPE_BASE_AUDIO_SRC, _do_init);
507
508 static GstRingBuffer *gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src);
509
510 static void
511 gst_audio_src_class_init (GstAudioSrcClass * klass)
512 {
513   GstBaseAudioSrcClass *gstbaseaudiosrc_class;
514
515   gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
516
517   gstbaseaudiosrc_class->create_ringbuffer =
518       GST_DEBUG_FUNCPTR (gst_audio_src_create_ringbuffer);
519
520   g_type_class_ref (GST_TYPE_AUDIO_SRC_RING_BUFFER);
521 }
522
523 static void
524 gst_audio_src_init (GstAudioSrc * audiosrc)
525 {
526 }
527
528 static GstRingBuffer *
529 gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
530 {
531   GstRingBuffer *buffer;
532
533   GST_DEBUG ("creating ringbuffer");
534   buffer = g_object_new (GST_TYPE_AUDIO_SRC_RING_BUFFER, NULL);
535   GST_DEBUG ("created ringbuffer @%p", buffer);
536
537   return buffer;
538 }