1c318e69028b74c418e4dc2ca1028520d1c7250e
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstaudiosink.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstaudiosink.c: simple audio sink 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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:gstaudiosink
25  * @short_description: Simple base class for audio sinks
26  * @see_also: #GstAudioBaseSink, #GstAudioRingBuffer, #GstAudioSink.
27  *
28  * This is the most simple base class for audio sinks 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>write()</term>
42  *     <listitem><para>Write samples to the device.</para></listitem>
43  *   </varlistentry>
44  *   <varlistentry>
45  *     <term>reset()</term>
46  *     <listitem><para>Unblock writes and flush the device.</para></listitem>
47  *   </varlistentry>
48  *   <varlistentry>
49  *     <term>delay()</term>
50  *     <listitem><para>Get the number of samples written but not yet played 
51  *     by the device.</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 #GstAudioBaseSink using a default implementation of a
65  * #GstAudioRingBuffer that uses threads.
66  *
67  * Last reviewed on 2006-09-27 (0.10.12)
68  */
69
70 #include <string.h>
71
72 #include <gst/audio/audio.h>
73 #include "gstaudiosink.h"
74
75 GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug);
76 #define GST_CAT_DEFAULT gst_audio_sink_debug
77
78 #define GST_TYPE_AUDIO_SINK_RING_BUFFER        \
79         (gst_audio_sink_ring_buffer_get_type())
80 #define GST_AUDIO_SINK_RING_BUFFER(obj)        \
81         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_SINK_RING_BUFFER,GstAudioSinkRingBuffer))
82 #define GST_AUDIO_SINK_RING_BUFFER_CLASS(klass) \
83         (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_SINK_RING_BUFFER,GstAudioSinkRingBufferClass))
84 #define GST_AUDIO_SINK_RING_BUFFER_GET_CLASS(obj) \
85         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIO_SINK_RING_BUFFER, GstAudioSinkRingBufferClass))
86 #define GST_AUDIO_SINK_RING_BUFFER_CAST(obj)        \
87         ((GstAudioSinkRingBuffer *)obj)
88 #define GST_IS_AUDIO_SINK_RING_BUFFER(obj)     \
89         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_SINK_RING_BUFFER))
90 #define GST_IS_AUDIO_SINK_RING_BUFFER_CLASS(klass)\
91         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_SINK_RING_BUFFER))
92
93 typedef struct _GstAudioSinkRingBuffer GstAudioSinkRingBuffer;
94 typedef struct _GstAudioSinkRingBufferClass GstAudioSinkRingBufferClass;
95
96 #define GST_AUDIO_SINK_RING_BUFFER_GET_COND(buf) (&(((GstAudioSinkRingBuffer *)buf)->cond))
97 #define GST_AUDIO_SINK_RING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIO_SINK_RING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
98 #define GST_AUDIO_SINK_RING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIO_SINK_RING_BUFFER_GET_COND (buf)))
99 #define GST_AUDIO_SINK_RING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIO_SINK_RING_BUFFER_GET_COND (buf)))
100
101 struct _GstAudioSinkRingBuffer
102 {
103   GstAudioRingBuffer object;
104
105   gboolean running;
106   gint queuedseg;
107
108   GCond cond;
109 };
110
111 struct _GstAudioSinkRingBufferClass
112 {
113   GstAudioRingBufferClass parent_class;
114 };
115
116 static void gst_audio_sink_ring_buffer_class_init (GstAudioSinkRingBufferClass *
117     klass);
118 static void gst_audio_sink_ring_buffer_init (GstAudioSinkRingBuffer *
119     ringbuffer, GstAudioSinkRingBufferClass * klass);
120 static void gst_audio_sink_ring_buffer_dispose (GObject * object);
121 static void gst_audio_sink_ring_buffer_finalize (GObject * object);
122
123 static GstAudioRingBufferClass *ring_parent_class = NULL;
124
125 static gboolean gst_audio_sink_ring_buffer_open_device (GstAudioRingBuffer *
126     buf);
127 static gboolean gst_audio_sink_ring_buffer_close_device (GstAudioRingBuffer *
128     buf);
129 static gboolean gst_audio_sink_ring_buffer_acquire (GstAudioRingBuffer * buf,
130     GstAudioRingBufferSpec * spec);
131 static gboolean gst_audio_sink_ring_buffer_release (GstAudioRingBuffer * buf);
132 static gboolean gst_audio_sink_ring_buffer_start (GstAudioRingBuffer * buf);
133 static gboolean gst_audio_sink_ring_buffer_pause (GstAudioRingBuffer * buf);
134 static gboolean gst_audio_sink_ring_buffer_stop (GstAudioRingBuffer * buf);
135 static guint gst_audio_sink_ring_buffer_delay (GstAudioRingBuffer * buf);
136 static gboolean gst_audio_sink_ring_buffer_activate (GstAudioRingBuffer * buf,
137     gboolean active);
138
139 /* ringbuffer abstract base class */
140 static GType
141 gst_audio_sink_ring_buffer_get_type (void)
142 {
143   static GType ringbuffer_type = 0;
144
145   if (!ringbuffer_type) {
146     static const GTypeInfo ringbuffer_info = {
147       sizeof (GstAudioSinkRingBufferClass),
148       NULL,
149       NULL,
150       (GClassInitFunc) gst_audio_sink_ring_buffer_class_init,
151       NULL,
152       NULL,
153       sizeof (GstAudioSinkRingBuffer),
154       0,
155       (GInstanceInitFunc) gst_audio_sink_ring_buffer_init,
156       NULL
157     };
158
159     ringbuffer_type =
160         g_type_register_static (GST_TYPE_AUDIO_RING_BUFFER,
161         "GstAudioSinkRingBuffer", &ringbuffer_info, 0);
162   }
163   return ringbuffer_type;
164 }
165
166 static void
167 gst_audio_sink_ring_buffer_class_init (GstAudioSinkRingBufferClass * klass)
168 {
169   GObjectClass *gobject_class;
170   GstAudioRingBufferClass *gstringbuffer_class;
171
172   gobject_class = (GObjectClass *) klass;
173   gstringbuffer_class = (GstAudioRingBufferClass *) klass;
174
175   ring_parent_class = g_type_class_peek_parent (klass);
176
177   gobject_class->dispose = gst_audio_sink_ring_buffer_dispose;
178   gobject_class->finalize = gst_audio_sink_ring_buffer_finalize;
179
180   gstringbuffer_class->open_device =
181       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_open_device);
182   gstringbuffer_class->close_device =
183       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_close_device);
184   gstringbuffer_class->acquire =
185       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_acquire);
186   gstringbuffer_class->release =
187       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_release);
188   gstringbuffer_class->start =
189       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_start);
190   gstringbuffer_class->pause =
191       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_pause);
192   gstringbuffer_class->resume =
193       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_start);
194   gstringbuffer_class->stop =
195       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_stop);
196
197   gstringbuffer_class->delay =
198       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_delay);
199   gstringbuffer_class->activate =
200       GST_DEBUG_FUNCPTR (gst_audio_sink_ring_buffer_activate);
201 }
202
203 typedef gint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
204
205 /* this internal thread does nothing else but write samples to the audio device.
206  * It will write each segment in the ringbuffer and will update the play
207  * pointer. 
208  * The start/stop methods control the thread.
209  */
210 static void
211 audioringbuffer_thread_func (GstAudioRingBuffer * buf)
212 {
213   GstAudioSink *sink;
214   GstAudioSinkClass *csink;
215   GstAudioSinkRingBuffer *abuf = GST_AUDIO_SINK_RING_BUFFER_CAST (buf);
216   WriteFunc writefunc;
217   GstMessage *message;
218   GValue val = { 0 };
219
220   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
221   csink = GST_AUDIO_SINK_GET_CLASS (sink);
222
223   GST_DEBUG_OBJECT (sink, "enter thread");
224
225   GST_OBJECT_LOCK (abuf);
226   GST_DEBUG_OBJECT (sink, "signal wait");
227   GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
228   GST_OBJECT_UNLOCK (abuf);
229
230   writefunc = csink->write;
231   if (writefunc == NULL)
232     goto no_function;
233
234   message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
235       GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink));
236   g_value_init (&val, GST_TYPE_G_THREAD);
237   g_value_set_boxed (&val, sink->thread);
238   gst_message_set_stream_status_object (message, &val);
239   g_value_unset (&val);
240   GST_DEBUG_OBJECT (sink, "posting ENTER stream status");
241   gst_element_post_message (GST_ELEMENT_CAST (sink), message);
242
243   while (TRUE) {
244     gint left, len;
245     guint8 *readptr;
246     gint readseg;
247
248     /* buffer must be started */
249     if (gst_audio_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
250       gint written;
251
252       left = len;
253       do {
254         written = writefunc (sink, readptr, left);
255         GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d",
256             written, left, readseg);
257         if (written < 0 || written > left) {
258           /* might not be critical, it e.g. happens when aborting playback */
259           GST_WARNING_OBJECT (sink,
260               "error writing data in %s (reason: %s), skipping segment (left: %d, written: %d)",
261               GST_DEBUG_FUNCPTR_NAME (writefunc),
262               (errno > 1 ? g_strerror (errno) : "unknown"), left, written);
263           break;
264         }
265         left -= written;
266         readptr += written;
267       } while (left > 0);
268
269       /* clear written samples */
270       gst_audio_ring_buffer_clear (buf, readseg);
271
272       /* we wrote one segment */
273       gst_audio_ring_buffer_advance (buf, 1);
274     } else {
275       GST_OBJECT_LOCK (abuf);
276       if (!abuf->running)
277         goto stop_running;
278       if (G_UNLIKELY (g_atomic_int_get (&buf->state) ==
279               GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
280         GST_OBJECT_UNLOCK (abuf);
281         continue;
282       }
283       GST_DEBUG_OBJECT (sink, "signal wait");
284       GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
285       GST_DEBUG_OBJECT (sink, "wait for action");
286       GST_AUDIO_SINK_RING_BUFFER_WAIT (buf);
287       GST_DEBUG_OBJECT (sink, "got signal");
288       if (!abuf->running)
289         goto stop_running;
290       GST_DEBUG_OBJECT (sink, "continue running");
291       GST_OBJECT_UNLOCK (abuf);
292     }
293   }
294
295   /* Will never be reached */
296   g_assert_not_reached ();
297   return;
298
299   /* ERROR */
300 no_function:
301   {
302     GST_DEBUG_OBJECT (sink, "no write function, exit thread");
303     return;
304   }
305 stop_running:
306   {
307     GST_OBJECT_UNLOCK (abuf);
308     GST_DEBUG_OBJECT (sink, "stop running, exit thread");
309     message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
310         GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (sink));
311     g_value_init (&val, GST_TYPE_G_THREAD);
312     g_value_set_boxed (&val, sink->thread);
313     gst_message_set_stream_status_object (message, &val);
314     g_value_unset (&val);
315     GST_DEBUG_OBJECT (sink, "posting LEAVE stream status");
316     gst_element_post_message (GST_ELEMENT_CAST (sink), message);
317     return;
318   }
319 }
320
321 static void
322 gst_audio_sink_ring_buffer_init (GstAudioSinkRingBuffer * ringbuffer,
323     GstAudioSinkRingBufferClass * g_class)
324 {
325   ringbuffer->running = FALSE;
326   ringbuffer->queuedseg = 0;
327
328   g_cond_init (&ringbuffer->cond);
329 }
330
331 static void
332 gst_audio_sink_ring_buffer_dispose (GObject * object)
333 {
334   G_OBJECT_CLASS (ring_parent_class)->dispose (object);
335 }
336
337 static void
338 gst_audio_sink_ring_buffer_finalize (GObject * object)
339 {
340   GstAudioSinkRingBuffer *ringbuffer = GST_AUDIO_SINK_RING_BUFFER_CAST (object);
341
342   g_cond_clear (&ringbuffer->cond);
343
344   G_OBJECT_CLASS (ring_parent_class)->finalize (object);
345 }
346
347 static gboolean
348 gst_audio_sink_ring_buffer_open_device (GstAudioRingBuffer * buf)
349 {
350   GstAudioSink *sink;
351   GstAudioSinkClass *csink;
352   gboolean result = TRUE;
353
354   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
355   csink = GST_AUDIO_SINK_GET_CLASS (sink);
356
357   if (csink->open)
358     result = csink->open (sink);
359
360   if (!result)
361     goto could_not_open;
362
363   return result;
364
365 could_not_open:
366   {
367     GST_DEBUG_OBJECT (sink, "could not open device");
368     return FALSE;
369   }
370 }
371
372 static gboolean
373 gst_audio_sink_ring_buffer_close_device (GstAudioRingBuffer * buf)
374 {
375   GstAudioSink *sink;
376   GstAudioSinkClass *csink;
377   gboolean result = TRUE;
378
379   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
380   csink = GST_AUDIO_SINK_GET_CLASS (sink);
381
382   if (csink->close)
383     result = csink->close (sink);
384
385   if (!result)
386     goto could_not_close;
387
388   return result;
389
390 could_not_close:
391   {
392     GST_DEBUG_OBJECT (sink, "could not close device");
393     return FALSE;
394   }
395 }
396
397 static gboolean
398 gst_audio_sink_ring_buffer_acquire (GstAudioRingBuffer * buf,
399     GstAudioRingBufferSpec * spec)
400 {
401   GstAudioSink *sink;
402   GstAudioSinkClass *csink;
403   gboolean result = FALSE;
404
405   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
406   csink = GST_AUDIO_SINK_GET_CLASS (sink);
407
408   if (csink->prepare)
409     result = csink->prepare (sink, spec);
410   if (!result)
411     goto could_not_prepare;
412
413   /* set latency to one more segment as we need some headroom */
414   spec->seglatency = spec->segtotal + 1;
415
416   buf->size = spec->segtotal * spec->segsize;
417   buf->memory = g_malloc0 (buf->size);
418
419   return TRUE;
420
421   /* ERRORS */
422 could_not_prepare:
423   {
424     GST_DEBUG_OBJECT (sink, "could not prepare device");
425     return FALSE;
426   }
427 }
428
429 static gboolean
430 gst_audio_sink_ring_buffer_activate (GstAudioRingBuffer * buf, gboolean active)
431 {
432   GstAudioSink *sink;
433   GstAudioSinkRingBuffer *abuf;
434   GError *error = NULL;
435
436   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
437   abuf = GST_AUDIO_SINK_RING_BUFFER_CAST (buf);
438
439   if (active) {
440     abuf->running = TRUE;
441
442     GST_DEBUG_OBJECT (sink, "starting thread");
443
444     sink->thread = g_thread_try_new ("audiosink-ringbuffer",
445         (GThreadFunc) audioringbuffer_thread_func, buf, &error);
446
447     if (!sink->thread || error != NULL)
448       goto thread_failed;
449
450     GST_DEBUG_OBJECT (sink, "waiting for thread");
451     /* the object lock is taken */
452     GST_AUDIO_SINK_RING_BUFFER_WAIT (buf);
453     GST_DEBUG_OBJECT (sink, "thread is started");
454   } else {
455     abuf->running = FALSE;
456     GST_DEBUG_OBJECT (sink, "signal wait");
457     GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
458
459     GST_OBJECT_UNLOCK (buf);
460
461     /* join the thread */
462     g_thread_join (sink->thread);
463
464     GST_OBJECT_LOCK (buf);
465   }
466   return TRUE;
467
468   /* ERRORS */
469 thread_failed:
470   {
471     if (error)
472       GST_ERROR_OBJECT (sink, "could not create thread %s", error->message);
473     else
474       GST_ERROR_OBJECT (sink, "could not create thread for unknown reason");
475     return FALSE;
476   }
477 }
478
479 /* function is called with LOCK */
480 static gboolean
481 gst_audio_sink_ring_buffer_release (GstAudioRingBuffer * buf)
482 {
483   GstAudioSink *sink;
484   GstAudioSinkClass *csink;
485   gboolean result = FALSE;
486
487   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
488   csink = GST_AUDIO_SINK_GET_CLASS (sink);
489
490   /* free the buffer */
491   g_free (buf->memory);
492   buf->memory = NULL;
493
494   if (csink->unprepare)
495     result = csink->unprepare (sink);
496
497   if (!result)
498     goto could_not_unprepare;
499
500   GST_DEBUG_OBJECT (sink, "unprepared");
501
502   return result;
503
504 could_not_unprepare:
505   {
506     GST_DEBUG_OBJECT (sink, "could not unprepare device");
507     return FALSE;
508   }
509 }
510
511 static gboolean
512 gst_audio_sink_ring_buffer_start (GstAudioRingBuffer * buf)
513 {
514   GstAudioSink *sink;
515
516   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
517
518   GST_DEBUG_OBJECT (sink, "start, sending signal");
519   GST_AUDIO_SINK_RING_BUFFER_SIGNAL (buf);
520
521   return TRUE;
522 }
523
524 static gboolean
525 gst_audio_sink_ring_buffer_pause (GstAudioRingBuffer * buf)
526 {
527   GstAudioSink *sink;
528   GstAudioSinkClass *csink;
529
530   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
531   csink = GST_AUDIO_SINK_GET_CLASS (sink);
532
533   /* unblock any pending writes to the audio device */
534   if (csink->reset) {
535     GST_DEBUG_OBJECT (sink, "reset...");
536     csink->reset (sink);
537     GST_DEBUG_OBJECT (sink, "reset done");
538   }
539
540   return TRUE;
541 }
542
543 static gboolean
544 gst_audio_sink_ring_buffer_stop (GstAudioRingBuffer * buf)
545 {
546   GstAudioSink *sink;
547   GstAudioSinkClass *csink;
548
549   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
550   csink = GST_AUDIO_SINK_GET_CLASS (sink);
551
552   /* unblock any pending writes to the audio device */
553   if (csink->reset) {
554     GST_DEBUG_OBJECT (sink, "reset...");
555     csink->reset (sink);
556     GST_DEBUG_OBJECT (sink, "reset done");
557   }
558 #if 0
559   if (abuf->running) {
560     GST_DEBUG_OBJECT (sink, "stop, waiting...");
561     GST_AUDIO_SINK_RING_BUFFER_WAIT (buf);
562     GST_DEBUG_OBJECT (sink, "stopped");
563   }
564 #endif
565
566   return TRUE;
567 }
568
569 static guint
570 gst_audio_sink_ring_buffer_delay (GstAudioRingBuffer * buf)
571 {
572   GstAudioSink *sink;
573   GstAudioSinkClass *csink;
574   guint res = 0;
575
576   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
577   csink = GST_AUDIO_SINK_GET_CLASS (sink);
578
579   if (csink->delay)
580     res = csink->delay (sink);
581
582   return res;
583 }
584
585 /* AudioSink signals and args */
586 enum
587 {
588   /* FILL ME */
589   LAST_SIGNAL
590 };
591
592 enum
593 {
594   ARG_0,
595 };
596
597 #define _do_init \
598     GST_DEBUG_CATEGORY_INIT (gst_audio_sink_debug, "audiosink", 0, "audiosink element");
599 #define gst_audio_sink_parent_class parent_class
600 G_DEFINE_TYPE_WITH_CODE (GstAudioSink, gst_audio_sink,
601     GST_TYPE_AUDIO_BASE_SINK, _do_init);
602
603 static GstAudioRingBuffer *gst_audio_sink_create_ringbuffer (GstAudioBaseSink *
604     sink);
605
606 static void
607 gst_audio_sink_class_init (GstAudioSinkClass * klass)
608 {
609   GstAudioBaseSinkClass *gstaudiobasesink_class;
610
611   gstaudiobasesink_class = (GstAudioBaseSinkClass *) klass;
612
613   gstaudiobasesink_class->create_ringbuffer =
614       GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer);
615
616   g_type_class_ref (GST_TYPE_AUDIO_SINK_RING_BUFFER);
617 }
618
619 static void
620 gst_audio_sink_init (GstAudioSink * audiosink)
621 {
622 }
623
624 static GstAudioRingBuffer *
625 gst_audio_sink_create_ringbuffer (GstAudioBaseSink * sink)
626 {
627   GstAudioRingBuffer *buffer;
628
629   GST_DEBUG_OBJECT (sink, "creating ringbuffer");
630   buffer = g_object_new (GST_TYPE_AUDIO_SINK_RING_BUFFER, NULL);
631   GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer);
632
633   return buffer;
634 }