gst_plugins_base/gst-libs/gst/audio/gstaudiosink.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     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., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 /**
       
    24  * SECTION:gstaudiosink
       
    25  * @short_description: Simple base class for audio sinks
       
    26  * @see_also: #GstBaseAudioSink, #GstRingBuffer, #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 #GstBaseAudioSink 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 "gstaudiosink.h"
       
    73 
       
    74 #ifdef __SYMBIAN32__
       
    75 #include <glib_global.h>
       
    76 #endif
       
    77 
       
    78 GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug);
       
    79 #define GST_CAT_DEFAULT gst_audio_sink_debug
       
    80 
       
    81 #define GST_TYPE_AUDIORING_BUFFER        \
       
    82         (gst_audioringbuffer_get_type())
       
    83 #define GST_AUDIORING_BUFFER(obj)        \
       
    84         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer))
       
    85 #define GST_AUDIORING_BUFFER_CLASS(klass) \
       
    86         (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass))
       
    87 #define GST_AUDIORING_BUFFER_GET_CLASS(obj) \
       
    88         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass))
       
    89 #define GST_AUDIORING_BUFFER_CAST(obj)        \
       
    90         ((GstAudioRingBuffer *)obj)
       
    91 #define GST_IS_AUDIORING_BUFFER(obj)     \
       
    92         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER))
       
    93 #define GST_IS_AUDIORING_BUFFER_CLASS(klass)\
       
    94         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER))
       
    95 
       
    96 typedef struct _GstAudioRingBuffer GstAudioRingBuffer;
       
    97 typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass;
       
    98 
       
    99 #define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond)
       
   100 #define GST_AUDIORING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
       
   101 #define GST_AUDIORING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf)))
       
   102 #define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf)))
       
   103 
       
   104 struct _GstAudioRingBuffer
       
   105 {
       
   106   GstRingBuffer object;
       
   107 
       
   108   gboolean running;
       
   109   gint queuedseg;
       
   110 
       
   111   GCond *cond;
       
   112 };
       
   113 
       
   114 struct _GstAudioRingBufferClass
       
   115 {
       
   116   GstRingBufferClass parent_class;
       
   117 };
       
   118 
       
   119 static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass);
       
   120 static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
       
   121     GstAudioRingBufferClass * klass);
       
   122 static void gst_audioringbuffer_dispose (GObject * object);
       
   123 static void gst_audioringbuffer_finalize (GObject * object);
       
   124 
       
   125 static GstRingBufferClass *ring_parent_class = NULL;
       
   126 
       
   127 static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf);
       
   128 static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf);
       
   129 static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
       
   130     GstRingBufferSpec * spec);
       
   131 static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
       
   132 static gboolean gst_audioringbuffer_start (GstRingBuffer * buf);
       
   133 static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf);
       
   134 static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
       
   135 static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
       
   136 
       
   137 /* ringbuffer abstract base class */
       
   138 static GType
       
   139 gst_audioringbuffer_get_type (void)
       
   140 {
       
   141   static GType ringbuffer_type = 0;
       
   142 
       
   143   if (!ringbuffer_type) {
       
   144     static const GTypeInfo ringbuffer_info = {
       
   145       sizeof (GstAudioRingBufferClass),
       
   146       NULL,
       
   147       NULL,
       
   148       (GClassInitFunc) gst_audioringbuffer_class_init,
       
   149       NULL,
       
   150       NULL,
       
   151       sizeof (GstAudioRingBuffer),
       
   152       0,
       
   153       (GInstanceInitFunc) gst_audioringbuffer_init,
       
   154       NULL
       
   155     };
       
   156 
       
   157     ringbuffer_type =
       
   158         g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSinkRingBuffer",
       
   159         &ringbuffer_info, 0);
       
   160   }
       
   161   return ringbuffer_type;
       
   162 }
       
   163 
       
   164 static void
       
   165 gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass)
       
   166 {
       
   167   GObjectClass *gobject_class;
       
   168   GstObjectClass *gstobject_class;
       
   169   GstRingBufferClass *gstringbuffer_class;
       
   170 
       
   171   gobject_class = (GObjectClass *) klass;
       
   172   gstobject_class = (GstObjectClass *) klass;
       
   173   gstringbuffer_class = (GstRingBufferClass *) klass;
       
   174 
       
   175   ring_parent_class = g_type_class_peek_parent (klass);
       
   176 
       
   177   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_audioringbuffer_dispose);
       
   178   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_audioringbuffer_finalize);
       
   179 
       
   180   gstringbuffer_class->open_device =
       
   181       GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device);
       
   182   gstringbuffer_class->close_device =
       
   183       GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device);
       
   184   gstringbuffer_class->acquire =
       
   185       GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
       
   186   gstringbuffer_class->release =
       
   187       GST_DEBUG_FUNCPTR (gst_audioringbuffer_release);
       
   188   gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
       
   189   gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_audioringbuffer_pause);
       
   190   gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
       
   191   gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
       
   192 
       
   193   gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
       
   194 }
       
   195 
       
   196 typedef guint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
       
   197 
       
   198 /* this internal thread does nothing else but write samples to the audio device.
       
   199  * It will write each segment in the ringbuffer and will update the play
       
   200  * pointer. 
       
   201  * The start/stop methods control the thread.
       
   202  */
       
   203 static void
       
   204 audioringbuffer_thread_func (GstRingBuffer * buf)
       
   205 {
       
   206   GstAudioSink *sink;
       
   207   GstAudioSinkClass *csink;
       
   208   GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER_CAST (buf);
       
   209   WriteFunc writefunc;
       
   210 
       
   211   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   212   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   213 
       
   214   GST_DEBUG_OBJECT (sink, "enter thread");
       
   215 
       
   216   writefunc = csink->write;
       
   217   if (writefunc == NULL)
       
   218     goto no_function;
       
   219 
       
   220   while (TRUE) {
       
   221     gint left, len;
       
   222     guint8 *readptr;
       
   223     gint readseg;
       
   224 
       
   225     if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
       
   226       gint written = 0;
       
   227 
       
   228       left = len;
       
   229       do {
       
   230         written = writefunc (sink, readptr + written, left);
       
   231         GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d",
       
   232             written, left, readseg);
       
   233         if (written < 0 || written > left) {
       
   234           GST_WARNING_OBJECT (sink,
       
   235               "error writing data (reason: %s), skipping segment",
       
   236               g_strerror (errno));
       
   237           break;
       
   238         }
       
   239         left -= written;
       
   240       } while (left > 0);
       
   241 
       
   242       /* clear written samples */
       
   243       gst_ring_buffer_clear (buf, readseg);
       
   244 
       
   245       /* we wrote one segment */
       
   246       gst_ring_buffer_advance (buf, 1);
       
   247     } else {
       
   248       GST_OBJECT_LOCK (abuf);
       
   249       if (!abuf->running)
       
   250         goto stop_running;
       
   251       GST_DEBUG_OBJECT (sink, "signal wait");
       
   252       GST_AUDIORING_BUFFER_SIGNAL (buf);
       
   253       GST_DEBUG_OBJECT (sink, "wait for action");
       
   254       GST_AUDIORING_BUFFER_WAIT (buf);
       
   255       GST_DEBUG_OBJECT (sink, "got signal");
       
   256       if (!abuf->running)
       
   257         goto stop_running;
       
   258       GST_DEBUG_OBJECT (sink, "continue running");
       
   259       GST_OBJECT_UNLOCK (abuf);
       
   260     }
       
   261   }
       
   262   GST_DEBUG_OBJECT (sink, "exit thread");
       
   263 
       
   264   return;
       
   265 
       
   266   /* ERROR */
       
   267 no_function:
       
   268   {
       
   269     GST_DEBUG_OBJECT (sink, "no write function, exit thread");
       
   270     return;
       
   271   }
       
   272 stop_running:
       
   273   {
       
   274     GST_OBJECT_UNLOCK (abuf);
       
   275     GST_DEBUG_OBJECT (sink, "stop running, exit thread");
       
   276     return;
       
   277   }
       
   278 }
       
   279 
       
   280 static void
       
   281 gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
       
   282     GstAudioRingBufferClass * g_class)
       
   283 {
       
   284   ringbuffer->running = FALSE;
       
   285   ringbuffer->queuedseg = 0;
       
   286 
       
   287   ringbuffer->cond = g_cond_new ();
       
   288 }
       
   289 
       
   290 static void
       
   291 gst_audioringbuffer_dispose (GObject * object)
       
   292 {
       
   293   G_OBJECT_CLASS (ring_parent_class)->dispose (object);
       
   294 }
       
   295 
       
   296 static void
       
   297 gst_audioringbuffer_finalize (GObject * object)
       
   298 {
       
   299   GstAudioRingBuffer *ringbuffer = GST_AUDIORING_BUFFER_CAST (object);
       
   300 
       
   301   g_cond_free (ringbuffer->cond);
       
   302 
       
   303   G_OBJECT_CLASS (ring_parent_class)->finalize (object);
       
   304 }
       
   305 
       
   306 static gboolean
       
   307 gst_audioringbuffer_open_device (GstRingBuffer * buf)
       
   308 {
       
   309   GstAudioSink *sink;
       
   310   GstAudioSinkClass *csink;
       
   311   gboolean result = TRUE;
       
   312 
       
   313   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   314   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   315 
       
   316   if (csink->open)
       
   317     result = csink->open (sink);
       
   318 
       
   319   if (!result)
       
   320     goto could_not_open;
       
   321 
       
   322   return result;
       
   323 
       
   324 could_not_open:
       
   325   {
       
   326     GST_DEBUG_OBJECT (sink, "could not open device");
       
   327     return FALSE;
       
   328   }
       
   329 }
       
   330 
       
   331 static gboolean
       
   332 gst_audioringbuffer_close_device (GstRingBuffer * buf)
       
   333 {
       
   334   GstAudioSink *sink;
       
   335   GstAudioSinkClass *csink;
       
   336   gboolean result = TRUE;
       
   337 
       
   338   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   339   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   340 
       
   341   if (csink->close)
       
   342     result = csink->close (sink);
       
   343 
       
   344   if (!result)
       
   345     goto could_not_close;
       
   346 
       
   347   return result;
       
   348 
       
   349 could_not_close:
       
   350   {
       
   351     GST_DEBUG_OBJECT (sink, "could not close device");
       
   352     return FALSE;
       
   353   }
       
   354 }
       
   355 
       
   356 static gboolean
       
   357 gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
       
   358 {
       
   359   GstAudioSink *sink;
       
   360   GstAudioSinkClass *csink;
       
   361   GstAudioRingBuffer *abuf;
       
   362   gboolean result = FALSE;
       
   363 
       
   364   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   365   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   366 
       
   367   if (csink->prepare)
       
   368     result = csink->prepare (sink, spec);
       
   369 
       
   370   if (!result)
       
   371     goto could_not_prepare;
       
   372 
       
   373   /* allocate one more segment as we need some headroom */
       
   374   spec->segtotal++;
       
   375 
       
   376   buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
       
   377   memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
       
   378 
       
   379   abuf = GST_AUDIORING_BUFFER_CAST (buf);
       
   380   abuf->running = TRUE;
       
   381 
       
   382   sink->thread =
       
   383       g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
       
   384       NULL);
       
   385   GST_AUDIORING_BUFFER_WAIT (buf);
       
   386 
       
   387   return result;
       
   388 
       
   389 could_not_prepare:
       
   390   {
       
   391     GST_DEBUG_OBJECT (sink, "could not prepare device");
       
   392     return FALSE;
       
   393   }
       
   394 }
       
   395 
       
   396 /* function is called with LOCK */
       
   397 static gboolean
       
   398 gst_audioringbuffer_release (GstRingBuffer * buf)
       
   399 {
       
   400   GstAudioSink *sink;
       
   401   GstAudioSinkClass *csink;
       
   402   GstAudioRingBuffer *abuf;
       
   403   gboolean result = FALSE;
       
   404 
       
   405   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   406   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   407   abuf = GST_AUDIORING_BUFFER_CAST (buf);
       
   408 
       
   409   abuf->running = FALSE;
       
   410   GST_DEBUG_OBJECT (sink, "signal wait");
       
   411   GST_AUDIORING_BUFFER_SIGNAL (buf);
       
   412   GST_OBJECT_UNLOCK (buf);
       
   413 
       
   414   /* join the thread */
       
   415   g_thread_join (sink->thread);
       
   416 
       
   417   GST_OBJECT_LOCK (buf);
       
   418 
       
   419   /* free the buffer */
       
   420   gst_buffer_unref (buf->data);
       
   421   buf->data = NULL;
       
   422 
       
   423   if (csink->unprepare)
       
   424     result = csink->unprepare (sink);
       
   425 
       
   426   if (!result)
       
   427     goto could_not_unprepare;
       
   428 
       
   429   return result;
       
   430 
       
   431 could_not_unprepare:
       
   432   {
       
   433     GST_DEBUG_OBJECT (sink, "could not unprepare device");
       
   434     return FALSE;
       
   435   }
       
   436 }
       
   437 
       
   438 static gboolean
       
   439 gst_audioringbuffer_start (GstRingBuffer * buf)
       
   440 {
       
   441   GstAudioSink *sink;
       
   442 
       
   443   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   444 
       
   445   GST_DEBUG_OBJECT (sink, "start, sending signal");
       
   446   GST_AUDIORING_BUFFER_SIGNAL (buf);
       
   447 
       
   448   return TRUE;
       
   449 }
       
   450 
       
   451 static gboolean
       
   452 gst_audioringbuffer_pause (GstRingBuffer * buf)
       
   453 {
       
   454   GstAudioSink *sink;
       
   455   GstAudioSinkClass *csink;
       
   456 
       
   457   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   458   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   459 
       
   460   /* unblock any pending writes to the audio device */
       
   461   if (csink->reset) {
       
   462     GST_DEBUG_OBJECT (sink, "reset...");
       
   463     csink->reset (sink);
       
   464     GST_DEBUG_OBJECT (sink, "reset done");
       
   465   }
       
   466 
       
   467   return TRUE;
       
   468 }
       
   469 
       
   470 static gboolean
       
   471 gst_audioringbuffer_stop (GstRingBuffer * buf)
       
   472 {
       
   473   GstAudioSink *sink;
       
   474   GstAudioSinkClass *csink;
       
   475   GstAudioRingBuffer *abuf;
       
   476 
       
   477   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   478   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   479   abuf = GST_AUDIORING_BUFFER_CAST (buf);
       
   480 
       
   481   /* unblock any pending writes to the audio device */
       
   482   if (csink->reset) {
       
   483     GST_DEBUG_OBJECT (sink, "reset...");
       
   484     csink->reset (sink);
       
   485     GST_DEBUG_OBJECT (sink, "reset done");
       
   486   }
       
   487 
       
   488   if (abuf->running) {
       
   489     GST_DEBUG_OBJECT (sink, "stop, waiting...");
       
   490     GST_AUDIORING_BUFFER_WAIT (buf);
       
   491     GST_DEBUG_OBJECT (sink, "stopped");
       
   492   }
       
   493 
       
   494   return TRUE;
       
   495 }
       
   496 
       
   497 static guint
       
   498 gst_audioringbuffer_delay (GstRingBuffer * buf)
       
   499 {
       
   500   GstAudioSink *sink;
       
   501   GstAudioSinkClass *csink;
       
   502   guint res = 0;
       
   503 
       
   504   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
       
   505   csink = GST_AUDIO_SINK_GET_CLASS (sink);
       
   506 
       
   507   if (csink->delay)
       
   508     res = csink->delay (sink);
       
   509 
       
   510   return res;
       
   511 }
       
   512 
       
   513 /* AudioSink signals and args */
       
   514 enum
       
   515 {
       
   516   /* FILL ME */
       
   517   LAST_SIGNAL
       
   518 };
       
   519 
       
   520 enum
       
   521 {
       
   522   ARG_0,
       
   523 };
       
   524 
       
   525 #define _do_init(bla) \
       
   526     GST_DEBUG_CATEGORY_INIT (gst_audio_sink_debug, "audiosink", 0, "audiosink element");
       
   527 
       
   528 GST_BOILERPLATE_FULL (GstAudioSink, gst_audio_sink, GstBaseAudioSink,
       
   529     GST_TYPE_BASE_AUDIO_SINK, _do_init);
       
   530 
       
   531 static GstRingBuffer *gst_audio_sink_create_ringbuffer (GstBaseAudioSink *
       
   532     sink);
       
   533 
       
   534 static void
       
   535 gst_audio_sink_base_init (gpointer g_class)
       
   536 {
       
   537 }
       
   538 
       
   539 static void
       
   540 gst_audio_sink_class_init (GstAudioSinkClass * klass)
       
   541 {
       
   542   GObjectClass *gobject_class;
       
   543   GstElementClass *gstelement_class;
       
   544   GstBaseSinkClass *gstbasesink_class;
       
   545   GstBaseAudioSinkClass *gstbaseaudiosink_class;
       
   546 
       
   547   gobject_class = (GObjectClass *) klass;
       
   548   gstelement_class = (GstElementClass *) klass;
       
   549   gstbasesink_class = (GstBaseSinkClass *) klass;
       
   550   gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
       
   551 
       
   552   gstbaseaudiosink_class->create_ringbuffer =
       
   553       GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer);
       
   554 }
       
   555 
       
   556 static void
       
   557 gst_audio_sink_init (GstAudioSink * audiosink, GstAudioSinkClass * g_class)
       
   558 {
       
   559 }
       
   560 
       
   561 static GstRingBuffer *
       
   562 gst_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
       
   563 {
       
   564   GstRingBuffer *buffer;
       
   565 
       
   566   GST_DEBUG_OBJECT (sink, "creating ringbuffer");
       
   567   buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL);
       
   568   GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer);
       
   569 
       
   570   return buffer;
       
   571 }