gst_plugins_base/gst-libs/gst/audio/gstringbuffer.c
changeset 0 0e761a78d257
child 7 567bb019e3e3
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /**
       
    21  * SECTION:gstringbuffer
       
    22  * @short_description: Base class for audio ringbuffer implementations
       
    23  * @see_also: #GstBaseAudioSink, #GstAudioSink
       
    24  *
       
    25  * <refsect2>
       
    26  * <para>
       
    27  * This object is the base class for audio ringbuffers used by the base
       
    28  * audio source and sink classes.
       
    29  * </para>
       
    30  * <para>
       
    31  * The ringbuffer abstracts a circular buffer of data. One reader and
       
    32  * one writer can operate on the data from different threads in a lockfree
       
    33  * manner. The base class is sufficiently flexible to be used as an
       
    34  * abstraction for DMA based ringbuffers as well as a pure software
       
    35  * implementations.
       
    36  * </para>
       
    37  * </refsect2>
       
    38  *
       
    39  * Last reviewed on 2006-02-02 (0.10.4)
       
    40  */
       
    41 
       
    42 #include <string.h>
       
    43 
       
    44 #include "gstringbuffer.h"
       
    45 
       
    46 #ifdef __SYMBIAN32__
       
    47 #include <glib_global.h>
       
    48 #endif
       
    49 
       
    50 GST_DEBUG_CATEGORY_STATIC (gst_ring_buffer_debug);
       
    51 #define GST_CAT_DEFAULT gst_ring_buffer_debug
       
    52 
       
    53 static void gst_ring_buffer_class_init (GstRingBufferClass * klass);
       
    54 static void gst_ring_buffer_init (GstRingBuffer * ringbuffer);
       
    55 static void gst_ring_buffer_dispose (GObject * object);
       
    56 static void gst_ring_buffer_finalize (GObject * object);
       
    57 
       
    58 static gboolean gst_ring_buffer_pause_unlocked (GstRingBuffer * buf);
       
    59 
       
    60 static GstObjectClass *parent_class = NULL;
       
    61 
       
    62 /* ringbuffer abstract base class */
       
    63 #ifdef __SYMBIAN32__
       
    64 EXPORT_C
       
    65 #endif
       
    66 
       
    67 GType
       
    68 gst_ring_buffer_get_type (void)
       
    69 {
       
    70   static GType ringbuffer_type = 0;
       
    71 
       
    72   if (G_UNLIKELY (!ringbuffer_type)) {
       
    73     static const GTypeInfo ringbuffer_info = {
       
    74       sizeof (GstRingBufferClass),
       
    75       NULL,
       
    76       NULL,
       
    77       (GClassInitFunc) gst_ring_buffer_class_init,
       
    78       NULL,
       
    79       NULL,
       
    80       sizeof (GstRingBuffer),
       
    81       0,
       
    82       (GInstanceInitFunc) gst_ring_buffer_init,
       
    83       NULL
       
    84     };
       
    85 
       
    86     ringbuffer_type = g_type_register_static (GST_TYPE_OBJECT, "GstRingBuffer",
       
    87         &ringbuffer_info, G_TYPE_FLAG_ABSTRACT);
       
    88 
       
    89     GST_DEBUG_CATEGORY_INIT (gst_ring_buffer_debug, "ringbuffer", 0,
       
    90         "ringbuffer class");
       
    91   }
       
    92   return ringbuffer_type;
       
    93 }
       
    94 
       
    95 static void
       
    96 gst_ring_buffer_class_init (GstRingBufferClass * klass)
       
    97 {
       
    98   GObjectClass *gobject_class;
       
    99   GstObjectClass *gstobject_class;
       
   100 
       
   101   gobject_class = (GObjectClass *) klass;
       
   102   gstobject_class = (GstObjectClass *) klass;
       
   103 
       
   104   parent_class = g_type_class_peek_parent (klass);
       
   105 
       
   106   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ring_buffer_dispose);
       
   107   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ring_buffer_finalize);
       
   108 }
       
   109 
       
   110 static void
       
   111 gst_ring_buffer_init (GstRingBuffer * ringbuffer)
       
   112 {
       
   113   ringbuffer->open = FALSE;
       
   114   ringbuffer->acquired = FALSE;
       
   115   ringbuffer->state = GST_RING_BUFFER_STATE_STOPPED;
       
   116   ringbuffer->cond = g_cond_new ();
       
   117   ringbuffer->waiting = 0;
       
   118   ringbuffer->empty_seg = NULL;
       
   119   ringbuffer->abidata.ABI.flushing = TRUE;
       
   120 }
       
   121 
       
   122 static void
       
   123 gst_ring_buffer_dispose (GObject * object)
       
   124 {
       
   125   GstRingBuffer *ringbuffer = GST_RING_BUFFER (object);
       
   126 
       
   127   gst_caps_replace (&ringbuffer->spec.caps, NULL);
       
   128 
       
   129   G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (ringbuffer));
       
   130 }
       
   131 
       
   132 static void
       
   133 gst_ring_buffer_finalize (GObject * object)
       
   134 {
       
   135   GstRingBuffer *ringbuffer = GST_RING_BUFFER (object);
       
   136 
       
   137   g_cond_free (ringbuffer->cond);
       
   138   g_free (ringbuffer->empty_seg);
       
   139 
       
   140   G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (ringbuffer));
       
   141 }
       
   142 
       
   143 typedef struct
       
   144 {
       
   145   const GstBufferFormat format;
       
   146   const guint8 silence[4];
       
   147 } FormatDef;
       
   148 
       
   149 static const FormatDef linear_defs[4 * 2 * 2] = {
       
   150   {GST_S8, {0x00, 0x00, 0x00, 0x00}},
       
   151   {GST_S8, {0x00, 0x00, 0x00, 0x00}},
       
   152   {GST_U8, {0x80, 0x80, 0x80, 0x80}},
       
   153   {GST_U8, {0x80, 0x80, 0x80, 0x80}},
       
   154   {GST_S16_LE, {0x00, 0x00, 0x00, 0x00}},
       
   155   {GST_S16_BE, {0x00, 0x00, 0x00, 0x00}},
       
   156   {GST_U16_LE, {0x00, 0x80, 0x00, 0x80}},
       
   157   {GST_U16_BE, {0x80, 0x00, 0x80, 0x00}},
       
   158   {GST_S24_LE, {0x00, 0x00, 0x00, 0x00}},
       
   159   {GST_S24_BE, {0x00, 0x00, 0x00, 0x00}},
       
   160   {GST_U24_LE, {0x00, 0x00, 0x80, 0x00}},
       
   161   {GST_U24_BE, {0x80, 0x00, 0x00, 0x00}},
       
   162   {GST_S32_LE, {0x00, 0x00, 0x00, 0x00}},
       
   163   {GST_S32_BE, {0x00, 0x00, 0x00, 0x00}},
       
   164   {GST_U32_LE, {0x00, 0x00, 0x00, 0x80}},
       
   165   {GST_U32_BE, {0x80, 0x00, 0x00, 0x00}}
       
   166 };
       
   167 
       
   168 static const FormatDef linear24_defs[3 * 2 * 2] = {
       
   169   {GST_S24_3LE, {0x00, 0x00, 0x00, 0x00}},
       
   170   {GST_S24_3BE, {0x00, 0x00, 0x00, 0x00}},
       
   171   {GST_U24_3LE, {0x00, 0x00, 0x80, 0x00}},
       
   172   {GST_U24_3BE, {0x80, 0x00, 0x00, 0x00}},
       
   173   {GST_S20_3LE, {0x00, 0x00, 0x00, 0x00}},
       
   174   {GST_S20_3BE, {0x00, 0x00, 0x00, 0x00}},
       
   175   {GST_U20_3LE, {0x00, 0x00, 0x08, 0x00}},
       
   176   {GST_U20_3BE, {0x08, 0x00, 0x00, 0x00}},
       
   177   {GST_S18_3LE, {0x00, 0x00, 0x00, 0x00}},
       
   178   {GST_S18_3BE, {0x00, 0x00, 0x00, 0x00}},
       
   179   {GST_U18_3LE, {0x00, 0x00, 0x02, 0x00}},
       
   180   {GST_U18_3BE, {0x02, 0x00, 0x00, 0x00}}
       
   181 };
       
   182 
       
   183 static const FormatDef *
       
   184 build_linear_format (int depth, int width, int unsignd, int big_endian)
       
   185 {
       
   186   const FormatDef *formats;
       
   187 
       
   188   if (width == 24) {
       
   189     switch (depth) {
       
   190       case 24:
       
   191         formats = &linear24_defs[0];
       
   192         break;
       
   193       case 20:
       
   194         formats = &linear24_defs[4];
       
   195         break;
       
   196       case 18:
       
   197         formats = &linear24_defs[8];
       
   198         break;
       
   199       default:
       
   200         return NULL;
       
   201     }
       
   202   } else {
       
   203     switch (depth) {
       
   204       case 8:
       
   205         formats = &linear_defs[0];
       
   206         break;
       
   207       case 16:
       
   208         formats = &linear_defs[4];
       
   209         break;
       
   210       case 24:
       
   211         formats = &linear_defs[8];
       
   212         break;
       
   213       case 32:
       
   214         formats = &linear_defs[12];
       
   215         break;
       
   216       default:
       
   217         return NULL;
       
   218     }
       
   219   }
       
   220   if (unsignd)
       
   221     formats += 2;
       
   222   if (big_endian)
       
   223     formats += 1;
       
   224 
       
   225   return formats;
       
   226 }
       
   227 
       
   228 /**
       
   229  * gst_ring_buffer_debug_spec_caps:
       
   230  * @spec: the spec to debug
       
   231  *
       
   232  * Print debug info about the parsed caps in @spec to the debug log.
       
   233  */
       
   234 #ifdef __SYMBIAN32__
       
   235 EXPORT_C
       
   236 #endif
       
   237 
       
   238 void
       
   239 gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
       
   240 {
       
   241   gint i, bytes;
       
   242 
       
   243   GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps);
       
   244   GST_DEBUG ("parsed caps: type:         %d", spec->type);
       
   245   GST_DEBUG ("parsed caps: format:       %d", spec->format);
       
   246   GST_DEBUG ("parsed caps: width:        %d", spec->width);
       
   247   GST_DEBUG ("parsed caps: depth:        %d", spec->depth);
       
   248   GST_DEBUG ("parsed caps: sign:         %d", spec->sign);
       
   249   GST_DEBUG ("parsed caps: bigend:       %d", spec->bigend);
       
   250   GST_DEBUG ("parsed caps: rate:         %d", spec->rate);
       
   251   GST_DEBUG ("parsed caps: channels:     %d", spec->channels);
       
   252   GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample);
       
   253   bytes = (spec->width >> 3) * spec->channels;
       
   254   for (i = 0; i < bytes; i++) {
       
   255     GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]);
       
   256   }
       
   257 }
       
   258 
       
   259 /**
       
   260  * gst_ring_buffer_debug_spec_buff:
       
   261  * @spec: the spec to debug
       
   262  *
       
   263  * Print debug info about the buffer sized in @spec to the debug log.
       
   264  */
       
   265 #ifdef __SYMBIAN32__
       
   266 EXPORT_C
       
   267 #endif
       
   268 
       
   269 void
       
   270 gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec)
       
   271 {
       
   272   GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec",
       
   273       spec->buffer_time);
       
   274   GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec",
       
   275       spec->latency_time);
       
   276   GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal);
       
   277   GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples",
       
   278       spec->segsize, spec->segsize / spec->bytes_per_sample);
       
   279   GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples",
       
   280       spec->segsize * spec->segtotal,
       
   281       spec->segsize * spec->segtotal / spec->bytes_per_sample);
       
   282 }
       
   283 
       
   284 /**
       
   285  * gst_ring_buffer_parse_caps:
       
   286  * @spec: a spec
       
   287  * @caps: a #GstCaps
       
   288  *
       
   289  * Parse @caps into @spec.
       
   290  *
       
   291  * Returns: TRUE if the caps could be parsed.
       
   292  */
       
   293 #ifdef __SYMBIAN32__
       
   294 EXPORT_C
       
   295 #endif
       
   296 
       
   297 gboolean
       
   298 gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
       
   299 {
       
   300   const gchar *mimetype;
       
   301   GstStructure *structure;
       
   302   gint i;
       
   303 
       
   304   structure = gst_caps_get_structure (caps, 0);
       
   305 
       
   306   /* we have to differentiate between int and float formats */
       
   307   mimetype = gst_structure_get_name (structure);
       
   308 
       
   309   if (!strncmp (mimetype, "audio/x-raw-int", 15)) {
       
   310     gint endianness;
       
   311     const FormatDef *def;
       
   312     gint j, bytes;
       
   313 
       
   314     spec->type = GST_BUFTYPE_LINEAR;
       
   315 
       
   316     /* extract the needed information from the cap */
       
   317     if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
       
   318             gst_structure_get_int (structure, "channels", &spec->channels) &&
       
   319             gst_structure_get_int (structure, "width", &spec->width) &&
       
   320             gst_structure_get_int (structure, "depth", &spec->depth) &&
       
   321             gst_structure_get_boolean (structure, "signed", &spec->sign)))
       
   322       goto parse_error;
       
   323 
       
   324     /* extract endianness if needed */
       
   325     if (spec->width > 8) {
       
   326       if (!gst_structure_get_int (structure, "endianness", &endianness))
       
   327         goto parse_error;
       
   328     } else {
       
   329       endianness = G_BYTE_ORDER;
       
   330     }
       
   331 
       
   332     spec->bigend = endianness == G_LITTLE_ENDIAN ? FALSE : TRUE;
       
   333 
       
   334     def = build_linear_format (spec->depth, spec->width, spec->sign ? 0 : 1,
       
   335         spec->bigend ? 1 : 0);
       
   336 
       
   337     if (def == NULL)
       
   338       goto parse_error;
       
   339 
       
   340     spec->format = def->format;
       
   341 
       
   342     bytes = spec->width >> 3;
       
   343 
       
   344     for (i = 0; i < spec->channels; i++) {
       
   345       for (j = 0; j < bytes; j++) {
       
   346         spec->silence_sample[i * bytes + j] = def->silence[j];
       
   347       }
       
   348     }
       
   349   } else if (!strncmp (mimetype, "audio/x-raw-float", 17)) {
       
   350 
       
   351     spec->type = GST_BUFTYPE_FLOAT;
       
   352 
       
   353     /* extract the needed information from the cap */
       
   354     if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
       
   355             gst_structure_get_int (structure, "channels", &spec->channels) &&
       
   356             gst_structure_get_int (structure, "width", &spec->width)))
       
   357       goto parse_error;
       
   358 
       
   359     /* match layout to format wrt to endianness */
       
   360     switch (spec->width) {
       
   361       case 32:
       
   362         spec->format =
       
   363             G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT32_LE : GST_FLOAT32_BE;
       
   364         break;
       
   365       case 64:
       
   366         spec->format =
       
   367             G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT64_LE : GST_FLOAT64_BE;
       
   368         break;
       
   369       default:
       
   370         goto parse_error;
       
   371     }
       
   372     /* float silence is all zeros.. */
       
   373     memset (spec->silence_sample, 0, 32);
       
   374   } else if (!strncmp (mimetype, "audio/x-alaw", 12)) {
       
   375     /* extract the needed information from the cap */
       
   376     if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
       
   377             gst_structure_get_int (structure, "channels", &spec->channels)))
       
   378       goto parse_error;
       
   379 
       
   380     spec->type = GST_BUFTYPE_A_LAW;
       
   381     spec->format = GST_A_LAW;
       
   382     spec->width = 8;
       
   383     spec->depth = 8;
       
   384     for (i = 0; i < spec->channels; i++)
       
   385       spec->silence_sample[i] = 0xd5;
       
   386   } else if (!strncmp (mimetype, "audio/x-mulaw", 13)) {
       
   387     /* extract the needed information from the cap */
       
   388     if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
       
   389             gst_structure_get_int (structure, "channels", &spec->channels)))
       
   390       goto parse_error;
       
   391 
       
   392     spec->type = GST_BUFTYPE_MU_LAW;
       
   393     spec->format = GST_MU_LAW;
       
   394     spec->width = 8;
       
   395     spec->depth = 8;
       
   396     for (i = 0; i < spec->channels; i++)
       
   397       spec->silence_sample[i] = 0xff;
       
   398   } else if (!strncmp (mimetype, "audio/x-iec958", 14)) {
       
   399     /* extract the needed information from the cap */
       
   400     if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
       
   401       goto parse_error;
       
   402 
       
   403     spec->type = GST_BUFTYPE_IEC958;
       
   404     spec->format = GST_IEC958;
       
   405     spec->width = 16;
       
   406     spec->depth = 16;
       
   407     spec->channels = 2;
       
   408   } else if (!strncmp (mimetype, "audio/x-ac3", 11)) {
       
   409     /* extract the needed information from the cap */
       
   410     if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
       
   411       goto parse_error;
       
   412 
       
   413     spec->type = GST_BUFTYPE_AC3;
       
   414     spec->format = GST_AC3;
       
   415     spec->width = 16;
       
   416     spec->depth = 16;
       
   417     spec->channels = 2;
       
   418   } else {
       
   419     goto parse_error;
       
   420   }
       
   421 
       
   422   spec->bytes_per_sample = (spec->width >> 3) * spec->channels;
       
   423 
       
   424   gst_caps_replace (&spec->caps, caps);
       
   425 
       
   426   g_return_val_if_fail (spec->latency_time != 0, FALSE);
       
   427 
       
   428   /* calculate suggested segsize and segtotal. segsize should be one unit
       
   429    * of 'latency_time' samples, scaling for the fact that latency_time is
       
   430    * currently stored in microseconds (FIXME: in 0.11) */
       
   431   spec->segsize = gst_util_uint64_scale (spec->rate * spec->bytes_per_sample,
       
   432       spec->latency_time, GST_SECOND / GST_USECOND);
       
   433   /* Round to an integer number of samples */
       
   434   spec->segsize -= spec->segsize % spec->bytes_per_sample;
       
   435 
       
   436   spec->segtotal = spec->buffer_time / spec->latency_time;
       
   437 
       
   438   gst_ring_buffer_debug_spec_caps (spec);
       
   439   gst_ring_buffer_debug_spec_buff (spec);
       
   440 
       
   441   return TRUE;
       
   442 
       
   443   /* ERRORS */
       
   444 parse_error:
       
   445   {
       
   446     GST_DEBUG ("could not parse caps");
       
   447     return FALSE;
       
   448   }
       
   449 }
       
   450 
       
   451 /**
       
   452  * gst_ring_buffer_set_callback:
       
   453  * @buf: the #GstRingBuffer to set the callback on
       
   454  * @cb: the callback to set
       
   455  * @user_data: user data passed to the callback
       
   456  *
       
   457  * Sets the given callback function on the buffer. This function
       
   458  * will be called every time a segment has been written to a device.
       
   459  *
       
   460  * MT safe.
       
   461  */
       
   462 #ifdef __SYMBIAN32__
       
   463 EXPORT_C
       
   464 #endif
       
   465 
       
   466 void
       
   467 gst_ring_buffer_set_callback (GstRingBuffer * buf, GstRingBufferCallback cb,
       
   468     gpointer user_data)
       
   469 {
       
   470   g_return_if_fail (GST_IS_RING_BUFFER (buf));
       
   471 
       
   472   GST_OBJECT_LOCK (buf);
       
   473   buf->callback = cb;
       
   474   buf->cb_data = user_data;
       
   475   GST_OBJECT_UNLOCK (buf);
       
   476 }
       
   477 
       
   478 
       
   479 /**
       
   480  * gst_ring_buffer_open_device:
       
   481  * @buf: the #GstRingBuffer
       
   482  *
       
   483  * Open the audio device associated with the ring buffer. Does not perform any
       
   484  * setup on the device. You must open the device before acquiring the ring
       
   485  * buffer.
       
   486  *
       
   487  * Returns: TRUE if the device could be opened, FALSE on error.
       
   488  *
       
   489  * MT safe.
       
   490  */
       
   491 #ifdef __SYMBIAN32__
       
   492 EXPORT_C
       
   493 #endif
       
   494 
       
   495 gboolean
       
   496 gst_ring_buffer_open_device (GstRingBuffer * buf)
       
   497 {
       
   498   gboolean res = TRUE;
       
   499   GstRingBufferClass *rclass;
       
   500 
       
   501   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
   502 
       
   503   GST_DEBUG_OBJECT (buf, "opening device");
       
   504 
       
   505   GST_OBJECT_LOCK (buf);
       
   506   if (G_UNLIKELY (buf->open))
       
   507     goto was_opened;
       
   508 
       
   509   buf->open = TRUE;
       
   510 
       
   511   /* if this fails, something is wrong in this file */
       
   512   g_assert (!buf->acquired);
       
   513 
       
   514   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
   515   if (G_LIKELY (rclass->open_device))
       
   516     res = rclass->open_device (buf);
       
   517 
       
   518   if (G_UNLIKELY (!res))
       
   519     goto open_failed;
       
   520 
       
   521   GST_DEBUG_OBJECT (buf, "opened device");
       
   522 
       
   523 done:
       
   524   GST_OBJECT_UNLOCK (buf);
       
   525 
       
   526   return res;
       
   527 
       
   528   /* ERRORS */
       
   529 was_opened:
       
   530   {
       
   531     GST_DEBUG_OBJECT (buf, "Device for ring buffer already open");
       
   532     g_warning ("Device for ring buffer %p already open, fix your code", buf);
       
   533     res = TRUE;
       
   534     goto done;
       
   535   }
       
   536 open_failed:
       
   537   {
       
   538     buf->open = FALSE;
       
   539     GST_DEBUG_OBJECT (buf, "failed opening device");
       
   540     goto done;
       
   541   }
       
   542 }
       
   543 
       
   544 /**
       
   545  * gst_ring_buffer_close_device:
       
   546  * @buf: the #GstRingBuffer
       
   547  *
       
   548  * Close the audio device associated with the ring buffer. The ring buffer
       
   549  * should already have been released via gst_ring_buffer_release().
       
   550  *
       
   551  * Returns: TRUE if the device could be closed, FALSE on error.
       
   552  *
       
   553  * MT safe.
       
   554  */
       
   555 #ifdef __SYMBIAN32__
       
   556 EXPORT_C
       
   557 #endif
       
   558 
       
   559 gboolean
       
   560 gst_ring_buffer_close_device (GstRingBuffer * buf)
       
   561 {
       
   562   gboolean res = TRUE;
       
   563   GstRingBufferClass *rclass;
       
   564 
       
   565   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
   566 
       
   567   GST_DEBUG_OBJECT (buf, "closing device");
       
   568 
       
   569   GST_OBJECT_LOCK (buf);
       
   570   if (G_UNLIKELY (!buf->open))
       
   571     goto was_closed;
       
   572 
       
   573   if (G_UNLIKELY (buf->acquired))
       
   574     goto was_acquired;
       
   575 
       
   576   buf->open = FALSE;
       
   577 
       
   578   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
   579   if (G_LIKELY (rclass->close_device))
       
   580     res = rclass->close_device (buf);
       
   581 
       
   582   if (G_UNLIKELY (!res))
       
   583     goto close_error;
       
   584 
       
   585   GST_DEBUG_OBJECT (buf, "closed device");
       
   586 
       
   587 done:
       
   588   GST_OBJECT_UNLOCK (buf);
       
   589 
       
   590   return res;
       
   591 
       
   592   /* ERRORS */
       
   593 was_closed:
       
   594   {
       
   595     GST_DEBUG_OBJECT (buf, "Device for ring buffer already closed");
       
   596     g_warning ("Device for ring buffer %p already closed, fix your code", buf);
       
   597     res = TRUE;
       
   598     goto done;
       
   599   }
       
   600 was_acquired:
       
   601   {
       
   602     GST_DEBUG_OBJECT (buf, "Resources for ring buffer still acquired");
       
   603     g_critical ("Resources for ring buffer %p still acquired", buf);
       
   604     res = FALSE;
       
   605     goto done;
       
   606   }
       
   607 close_error:
       
   608   {
       
   609     buf->open = TRUE;
       
   610     GST_DEBUG_OBJECT (buf, "error closing device");
       
   611     goto done;
       
   612   }
       
   613 }
       
   614 
       
   615 /**
       
   616  * gst_ring_buffer_device_is_open:
       
   617  * @buf: the #GstRingBuffer
       
   618  *
       
   619  * Checks the status of the device associated with the ring buffer.
       
   620  *
       
   621  * Returns: TRUE if the device was open, FALSE if it was closed.
       
   622  *
       
   623  * MT safe.
       
   624  */
       
   625 #ifdef __SYMBIAN32__
       
   626 EXPORT_C
       
   627 #endif
       
   628 
       
   629 gboolean
       
   630 gst_ring_buffer_device_is_open (GstRingBuffer * buf)
       
   631 {
       
   632   gboolean res = TRUE;
       
   633 
       
   634   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
   635 
       
   636   GST_OBJECT_LOCK (buf);
       
   637   res = buf->open;
       
   638   GST_OBJECT_UNLOCK (buf);
       
   639 
       
   640   return res;
       
   641 }
       
   642 
       
   643 
       
   644 /**
       
   645  * gst_ring_buffer_acquire:
       
   646  * @buf: the #GstRingBuffer to acquire
       
   647  * @spec: the specs of the buffer
       
   648  *
       
   649  * Allocate the resources for the ringbuffer. This function fills
       
   650  * in the data pointer of the ring buffer with a valid #GstBuffer
       
   651  * to which samples can be written.
       
   652  *
       
   653  * Returns: TRUE if the device could be acquired, FALSE on error.
       
   654  *
       
   655  * MT safe.
       
   656  */
       
   657 #ifdef __SYMBIAN32__
       
   658 EXPORT_C
       
   659 #endif
       
   660 
       
   661 gboolean
       
   662 gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
       
   663 {
       
   664   gboolean res = FALSE;
       
   665   GstRingBufferClass *rclass;
       
   666   gint i, j;
       
   667   gint segsize, bps;
       
   668 
       
   669   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
   670 
       
   671   GST_DEBUG_OBJECT (buf, "acquiring device");
       
   672 
       
   673   GST_OBJECT_LOCK (buf);
       
   674   if (G_UNLIKELY (!buf->open))
       
   675     goto not_opened;
       
   676 
       
   677   if (G_UNLIKELY (buf->acquired))
       
   678     goto was_acquired;
       
   679 
       
   680   buf->acquired = TRUE;
       
   681 
       
   682   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
   683   if (G_LIKELY (rclass->acquire))
       
   684     res = rclass->acquire (buf, spec);
       
   685 
       
   686   if (G_UNLIKELY (!res))
       
   687     goto acquire_failed;
       
   688 
       
   689   if (G_UNLIKELY ((bps = buf->spec.bytes_per_sample) == 0))
       
   690     goto invalid_bps;
       
   691 
       
   692   segsize = buf->spec.segsize;
       
   693 
       
   694   buf->samples_per_seg = segsize / bps;
       
   695 
       
   696   /* create an empty segment */
       
   697   g_free (buf->empty_seg);
       
   698   buf->empty_seg = g_malloc (segsize);
       
   699 
       
   700   /* FIXME, we only have 32 silence samples, which might not be enough to
       
   701    * represent silence in all channels */
       
   702   bps = MIN (bps, 32);
       
   703   for (i = 0, j = 0; i < segsize; i++) {
       
   704     buf->empty_seg[i] = buf->spec.silence_sample[j];
       
   705     j = (j + 1) % bps;
       
   706   }
       
   707   GST_DEBUG_OBJECT (buf, "acquired device");
       
   708 
       
   709 done:
       
   710   GST_OBJECT_UNLOCK (buf);
       
   711 
       
   712   return res;
       
   713 
       
   714   /* ERRORS */
       
   715 not_opened:
       
   716   {
       
   717     GST_DEBUG_OBJECT (buf, "device not opened");
       
   718     g_critical ("Device for %p not opened", buf);
       
   719     res = FALSE;
       
   720     goto done;
       
   721   }
       
   722 was_acquired:
       
   723   {
       
   724     res = TRUE;
       
   725     GST_DEBUG_OBJECT (buf, "device was acquired");
       
   726     goto done;
       
   727   }
       
   728 acquire_failed:
       
   729   {
       
   730     buf->acquired = FALSE;
       
   731     GST_DEBUG_OBJECT (buf, "failed to acquire device");
       
   732     goto done;
       
   733   }
       
   734 invalid_bps:
       
   735   {
       
   736     g_warning
       
   737         ("invalid bytes_per_sample from acquire ringbuffer, fix the element");
       
   738     buf->acquired = FALSE;
       
   739     res = FALSE;
       
   740     goto done;
       
   741   }
       
   742 }
       
   743 
       
   744 /**
       
   745  * gst_ring_buffer_release:
       
   746  * @buf: the #GstRingBuffer to release
       
   747  *
       
   748  * Free the resources of the ringbuffer.
       
   749  *
       
   750  * Returns: TRUE if the device could be released, FALSE on error.
       
   751  *
       
   752  * MT safe.
       
   753  */
       
   754 #ifdef __SYMBIAN32__
       
   755 EXPORT_C
       
   756 #endif
       
   757 
       
   758 gboolean
       
   759 gst_ring_buffer_release (GstRingBuffer * buf)
       
   760 {
       
   761   gboolean res = FALSE;
       
   762   GstRingBufferClass *rclass;
       
   763 
       
   764   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
   765 
       
   766   GST_DEBUG_OBJECT (buf, "releasing device");
       
   767 
       
   768   gst_ring_buffer_stop (buf);
       
   769 
       
   770   GST_OBJECT_LOCK (buf);
       
   771   if (G_UNLIKELY (!buf->acquired))
       
   772     goto was_released;
       
   773 
       
   774   buf->acquired = FALSE;
       
   775 
       
   776   /* if this fails, something is wrong in this file */
       
   777   g_assert (buf->open == TRUE);
       
   778 
       
   779   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
   780   if (G_LIKELY (rclass->release))
       
   781     res = rclass->release (buf);
       
   782 
       
   783   /* signal any waiters */
       
   784   GST_DEBUG_OBJECT (buf, "signal waiter");
       
   785   GST_RING_BUFFER_SIGNAL (buf);
       
   786 
       
   787   if (G_UNLIKELY (!res))
       
   788     goto release_failed;
       
   789 
       
   790   g_free (buf->empty_seg);
       
   791   buf->empty_seg = NULL;
       
   792   GST_DEBUG_OBJECT (buf, "released device");
       
   793 
       
   794 done:
       
   795   GST_OBJECT_UNLOCK (buf);
       
   796 
       
   797   return res;
       
   798 
       
   799   /* ERRORS */
       
   800 was_released:
       
   801   {
       
   802     res = TRUE;
       
   803     GST_DEBUG_OBJECT (buf, "device was released");
       
   804     goto done;
       
   805   }
       
   806 release_failed:
       
   807   {
       
   808     buf->acquired = TRUE;
       
   809     GST_DEBUG_OBJECT (buf, "failed to release device");
       
   810     goto done;
       
   811   }
       
   812 }
       
   813 
       
   814 /**
       
   815  * gst_ring_buffer_is_acquired:
       
   816  * @buf: the #GstRingBuffer to check
       
   817  *
       
   818  * Check if the ringbuffer is acquired and ready to use.
       
   819  *
       
   820  * Returns: TRUE if the ringbuffer is acquired, FALSE on error.
       
   821  *
       
   822  * MT safe.
       
   823  */
       
   824 #ifdef __SYMBIAN32__
       
   825 EXPORT_C
       
   826 #endif
       
   827 
       
   828 gboolean
       
   829 gst_ring_buffer_is_acquired (GstRingBuffer * buf)
       
   830 {
       
   831   gboolean res;
       
   832 
       
   833   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
   834 
       
   835   GST_OBJECT_LOCK (buf);
       
   836   res = buf->acquired;
       
   837   GST_OBJECT_UNLOCK (buf);
       
   838 
       
   839   return res;
       
   840 }
       
   841 
       
   842 /**
       
   843  * gst_ring_buffer_set_flushing:
       
   844  * @buf: the #GstRingBuffer to flush
       
   845  * @flushing: the new mode
       
   846  *
       
   847  * Set the ringbuffer to flushing mode or normal mode.
       
   848  *
       
   849  * MT safe.
       
   850  */
       
   851 #ifdef __SYMBIAN32__
       
   852 EXPORT_C
       
   853 #endif
       
   854 
       
   855 void
       
   856 gst_ring_buffer_set_flushing (GstRingBuffer * buf, gboolean flushing)
       
   857 {
       
   858   g_return_if_fail (GST_IS_RING_BUFFER (buf));
       
   859 
       
   860   GST_OBJECT_LOCK (buf);
       
   861   buf->abidata.ABI.flushing = flushing;
       
   862 
       
   863   gst_ring_buffer_clear_all (buf);
       
   864   if (flushing) {
       
   865     gst_ring_buffer_pause_unlocked (buf);
       
   866   }
       
   867   GST_OBJECT_UNLOCK (buf);
       
   868 }
       
   869 
       
   870 /**
       
   871  * gst_ring_buffer_start:
       
   872  * @buf: the #GstRingBuffer to start
       
   873  *
       
   874  * Start processing samples from the ringbuffer.
       
   875  *
       
   876  * Returns: TRUE if the device could be started, FALSE on error.
       
   877  *
       
   878  * MT safe.
       
   879  */
       
   880 #ifdef __SYMBIAN32__
       
   881 EXPORT_C
       
   882 #endif
       
   883 
       
   884 gboolean
       
   885 gst_ring_buffer_start (GstRingBuffer * buf)
       
   886 {
       
   887   gboolean res = FALSE;
       
   888   GstRingBufferClass *rclass;
       
   889   gboolean resume = FALSE;
       
   890 
       
   891   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
   892 
       
   893   GST_DEBUG_OBJECT (buf, "starting ringbuffer");
       
   894 
       
   895   GST_OBJECT_LOCK (buf);
       
   896   if (G_UNLIKELY (buf->abidata.ABI.flushing))
       
   897     goto flushing;
       
   898 
       
   899   if (G_UNLIKELY (!buf->acquired))
       
   900     goto not_acquired;
       
   901 
       
   902   /* if stopped, set to started */
       
   903   res = g_atomic_int_compare_and_exchange (&buf->state,
       
   904       GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STARTED);
       
   905 
       
   906   if (!res) {
       
   907     /* was not stopped, try from paused */
       
   908     res = g_atomic_int_compare_and_exchange (&buf->state,
       
   909         GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STARTED);
       
   910     if (!res) {
       
   911       /* was not paused either, must be started then */
       
   912       res = TRUE;
       
   913       GST_DEBUG_OBJECT (buf, "was started");
       
   914       goto done;
       
   915     }
       
   916     resume = TRUE;
       
   917     GST_DEBUG_OBJECT (buf, "resuming");
       
   918   }
       
   919 
       
   920   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
   921   if (resume) {
       
   922     if (G_LIKELY (rclass->resume))
       
   923       res = rclass->resume (buf);
       
   924   } else {
       
   925     if (G_LIKELY (rclass->start))
       
   926       res = rclass->start (buf);
       
   927   }
       
   928 
       
   929   if (G_UNLIKELY (!res)) {
       
   930     buf->state = GST_RING_BUFFER_STATE_PAUSED;
       
   931     GST_DEBUG_OBJECT (buf, "failed to start");
       
   932   } else {
       
   933     GST_DEBUG_OBJECT (buf, "started");
       
   934   }
       
   935 
       
   936 done:
       
   937   GST_OBJECT_UNLOCK (buf);
       
   938 
       
   939   return res;
       
   940 
       
   941 flushing:
       
   942   {
       
   943     GST_DEBUG_OBJECT (buf, "we are flushing");
       
   944     GST_OBJECT_UNLOCK (buf);
       
   945     return FALSE;
       
   946   }
       
   947 not_acquired:
       
   948   {
       
   949     GST_DEBUG_OBJECT (buf, "we are not acquired");
       
   950     GST_OBJECT_UNLOCK (buf);
       
   951     return FALSE;
       
   952   }
       
   953 }
       
   954 
       
   955 static gboolean
       
   956 gst_ring_buffer_pause_unlocked (GstRingBuffer * buf)
       
   957 {
       
   958   gboolean res = FALSE;
       
   959   GstRingBufferClass *rclass;
       
   960 
       
   961   GST_DEBUG_OBJECT (buf, "pausing ringbuffer");
       
   962 
       
   963   /* if started, set to paused */
       
   964   res = g_atomic_int_compare_and_exchange (&buf->state,
       
   965       GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_PAUSED);
       
   966 
       
   967   if (!res)
       
   968     goto not_started;
       
   969 
       
   970   /* signal any waiters */
       
   971   GST_DEBUG_OBJECT (buf, "signal waiter");
       
   972   GST_RING_BUFFER_SIGNAL (buf);
       
   973 
       
   974   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
   975   if (G_LIKELY (rclass->pause))
       
   976     res = rclass->pause (buf);
       
   977 
       
   978   if (G_UNLIKELY (!res)) {
       
   979     buf->state = GST_RING_BUFFER_STATE_STARTED;
       
   980     GST_DEBUG_OBJECT (buf, "failed to pause");
       
   981   } else {
       
   982     GST_DEBUG_OBJECT (buf, "paused");
       
   983   }
       
   984 
       
   985   return res;
       
   986 
       
   987 not_started:
       
   988   {
       
   989     /* was not started */
       
   990     GST_DEBUG_OBJECT (buf, "was not started");
       
   991     return TRUE;
       
   992   }
       
   993 }
       
   994 
       
   995 /**
       
   996  * gst_ring_buffer_pause:
       
   997  * @buf: the #GstRingBuffer to pause
       
   998  *
       
   999  * Pause processing samples from the ringbuffer.
       
  1000  *
       
  1001  * Returns: TRUE if the device could be paused, FALSE on error.
       
  1002  *
       
  1003  * MT safe.
       
  1004  */
       
  1005 #ifdef __SYMBIAN32__
       
  1006 EXPORT_C
       
  1007 #endif
       
  1008 
       
  1009 gboolean
       
  1010 gst_ring_buffer_pause (GstRingBuffer * buf)
       
  1011 {
       
  1012   gboolean res = FALSE;
       
  1013 
       
  1014   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
  1015 
       
  1016   GST_OBJECT_LOCK (buf);
       
  1017   if (G_UNLIKELY (buf->abidata.ABI.flushing))
       
  1018     goto flushing;
       
  1019 
       
  1020   if (G_UNLIKELY (!buf->acquired))
       
  1021     goto not_acquired;
       
  1022 
       
  1023   res = gst_ring_buffer_pause_unlocked (buf);
       
  1024   GST_OBJECT_UNLOCK (buf);
       
  1025 
       
  1026   return res;
       
  1027 
       
  1028   /* ERRORS */
       
  1029 flushing:
       
  1030   {
       
  1031     GST_DEBUG_OBJECT (buf, "we are flushing");
       
  1032     GST_OBJECT_UNLOCK (buf);
       
  1033     return FALSE;
       
  1034   }
       
  1035 not_acquired:
       
  1036   {
       
  1037     GST_DEBUG_OBJECT (buf, "not acquired");
       
  1038     GST_OBJECT_UNLOCK (buf);
       
  1039     return FALSE;
       
  1040   }
       
  1041 }
       
  1042 
       
  1043 /**
       
  1044  * gst_ring_buffer_stop:
       
  1045  * @buf: the #GstRingBuffer to stop
       
  1046  *
       
  1047  * Stop processing samples from the ringbuffer.
       
  1048  *
       
  1049  * Returns: TRUE if the device could be stopped, FALSE on error.
       
  1050  *
       
  1051  * MT safe.
       
  1052  */
       
  1053 #ifdef __SYMBIAN32__
       
  1054 EXPORT_C
       
  1055 #endif
       
  1056 
       
  1057 gboolean
       
  1058 gst_ring_buffer_stop (GstRingBuffer * buf)
       
  1059 {
       
  1060   gboolean res = FALSE;
       
  1061   GstRingBufferClass *rclass;
       
  1062 
       
  1063   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
  1064 
       
  1065   GST_DEBUG_OBJECT (buf, "stopping");
       
  1066 
       
  1067   GST_OBJECT_LOCK (buf);
       
  1068 
       
  1069   /* if started, set to stopped */
       
  1070   res = g_atomic_int_compare_and_exchange (&buf->state,
       
  1071       GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STOPPED);
       
  1072 
       
  1073   if (!res) {
       
  1074     /* was not started, must be stopped then */
       
  1075     GST_DEBUG_OBJECT (buf, "was not started");
       
  1076     res = TRUE;
       
  1077     goto done;
       
  1078   }
       
  1079 
       
  1080   /* signal any waiters */
       
  1081   GST_DEBUG_OBJECT (buf, "signal waiter");
       
  1082   GST_RING_BUFFER_SIGNAL (buf);
       
  1083 
       
  1084   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
  1085   if (G_LIKELY (rclass->stop))
       
  1086     res = rclass->stop (buf);
       
  1087 
       
  1088   if (G_UNLIKELY (!res)) {
       
  1089     buf->state = GST_RING_BUFFER_STATE_STARTED;
       
  1090     GST_DEBUG_OBJECT (buf, "failed to stop");
       
  1091   } else {
       
  1092     GST_DEBUG_OBJECT (buf, "stopped");
       
  1093   }
       
  1094 done:
       
  1095   GST_OBJECT_UNLOCK (buf);
       
  1096 
       
  1097   return res;
       
  1098 }
       
  1099 
       
  1100 /**
       
  1101  * gst_ring_buffer_delay:
       
  1102  * @buf: the #GstRingBuffer to query
       
  1103  *
       
  1104  * Get the number of samples queued in the audio device. This is
       
  1105  * usually less than the segment size but can be bigger when the
       
  1106  * implementation uses another internal buffer between the audio
       
  1107  * device.
       
  1108  *
       
  1109  * For playback ringbuffers this is the amount of samples transfered from the
       
  1110  * ringbuffer to the device but still not played.
       
  1111  *
       
  1112  * For capture ringbuffers this is the amount of samples in the device that are
       
  1113  * not yet transfered to the ringbuffer.
       
  1114  *
       
  1115  * Returns: The number of samples queued in the audio device.
       
  1116  *
       
  1117  * MT safe.
       
  1118  */
       
  1119 #ifdef __SYMBIAN32__
       
  1120 EXPORT_C
       
  1121 #endif
       
  1122 
       
  1123 guint
       
  1124 gst_ring_buffer_delay (GstRingBuffer * buf)
       
  1125 {
       
  1126   GstRingBufferClass *rclass;
       
  1127   guint res;
       
  1128 
       
  1129   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0);
       
  1130 
       
  1131   /* buffer must be acquired */
       
  1132   if (G_UNLIKELY (!gst_ring_buffer_is_acquired (buf)))
       
  1133     goto not_acquired;
       
  1134 
       
  1135   rclass = GST_RING_BUFFER_GET_CLASS (buf);
       
  1136   if (G_LIKELY (rclass->delay))
       
  1137     res = rclass->delay (buf);
       
  1138   else
       
  1139     res = 0;
       
  1140 
       
  1141   return res;
       
  1142 
       
  1143 not_acquired:
       
  1144   {
       
  1145     GST_DEBUG_OBJECT (buf, "not acquired");
       
  1146     return 0;
       
  1147   }
       
  1148 }
       
  1149 
       
  1150 /**
       
  1151  * gst_ring_buffer_samples_done:
       
  1152  * @buf: the #GstRingBuffer to query
       
  1153  *
       
  1154  * Get the number of samples that were processed by the ringbuffer
       
  1155  * since it was last started. This does not include the number of samples not
       
  1156  * yet processed (see gst_ring_buffer_delay()).
       
  1157  *
       
  1158  * Returns: The number of samples processed by the ringbuffer.
       
  1159  *
       
  1160  * MT safe.
       
  1161  */
       
  1162 #ifdef __SYMBIAN32__
       
  1163 EXPORT_C
       
  1164 #endif
       
  1165 
       
  1166 guint64
       
  1167 gst_ring_buffer_samples_done (GstRingBuffer * buf)
       
  1168 {
       
  1169   gint segdone;
       
  1170   guint64 samples;
       
  1171 
       
  1172   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0);
       
  1173 
       
  1174   /* get the amount of segments we processed */
       
  1175   segdone = g_atomic_int_get (&buf->segdone);
       
  1176 
       
  1177   /* convert to samples */
       
  1178   samples = ((guint64) segdone) * buf->samples_per_seg;
       
  1179 
       
  1180   return samples;
       
  1181 }
       
  1182 
       
  1183 /**
       
  1184  * gst_ring_buffer_set_sample:
       
  1185  * @buf: the #GstRingBuffer to use
       
  1186  * @sample: the sample number to set
       
  1187  *
       
  1188  * Make sure that the next sample written to the device is
       
  1189  * accounted for as being the @sample sample written to the
       
  1190  * device. This value will be used in reporting the current
       
  1191  * sample position of the ringbuffer.
       
  1192  *
       
  1193  * This function will also clear the buffer with silence.
       
  1194  *
       
  1195  * MT safe.
       
  1196  */
       
  1197 #ifdef __SYMBIAN32__
       
  1198 EXPORT_C
       
  1199 #endif
       
  1200 
       
  1201 void
       
  1202 gst_ring_buffer_set_sample (GstRingBuffer * buf, guint64 sample)
       
  1203 {
       
  1204   g_return_if_fail (GST_IS_RING_BUFFER (buf));
       
  1205 
       
  1206   if (sample == -1)
       
  1207     sample = 0;
       
  1208 
       
  1209   if (G_UNLIKELY (buf->samples_per_seg == 0))
       
  1210     return;
       
  1211 
       
  1212   /* FIXME, we assume the ringbuffer can restart at a random 
       
  1213    * position, round down to the beginning and keep track of
       
  1214    * offset when calculating the processed samples. */
       
  1215   buf->segbase = buf->segdone - sample / buf->samples_per_seg;
       
  1216 
       
  1217   gst_ring_buffer_clear_all (buf);
       
  1218 
       
  1219   GST_DEBUG_OBJECT (buf, "set sample to %llu, segbase %d", sample,
       
  1220       buf->segbase);
       
  1221 }
       
  1222 
       
  1223 /**
       
  1224  * gst_ring_buffer_clear_all:
       
  1225  * @buf: the #GstRingBuffer to clear
       
  1226  *
       
  1227  * Fill the ringbuffer with silence.
       
  1228  *
       
  1229  * MT safe.
       
  1230  */
       
  1231 #ifdef __SYMBIAN32__
       
  1232 EXPORT_C
       
  1233 #endif
       
  1234 
       
  1235 void
       
  1236 gst_ring_buffer_clear_all (GstRingBuffer * buf)
       
  1237 {
       
  1238   gint i;
       
  1239 
       
  1240   g_return_if_fail (GST_IS_RING_BUFFER (buf));
       
  1241 
       
  1242   /* not fatal, we just are not negotiated yet */
       
  1243   if (G_UNLIKELY (buf->spec.segtotal <= 0))
       
  1244     return;
       
  1245 
       
  1246   GST_DEBUG_OBJECT (buf, "clear all segments");
       
  1247 
       
  1248   for (i = 0; i < buf->spec.segtotal; i++) {
       
  1249     gst_ring_buffer_clear (buf, i);
       
  1250   }
       
  1251 }
       
  1252 
       
  1253 
       
  1254 static gboolean
       
  1255 wait_segment (GstRingBuffer * buf)
       
  1256 {
       
  1257   /* buffer must be started now or we deadlock since nobody is reading */
       
  1258   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
       
  1259           GST_RING_BUFFER_STATE_STARTED)) {
       
  1260     /* see if we are allowed to start it */
       
  1261     if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE))
       
  1262       goto no_start;
       
  1263 
       
  1264     GST_DEBUG_OBJECT (buf, "start!");
       
  1265     gst_ring_buffer_start (buf);
       
  1266   }
       
  1267 
       
  1268   /* take lock first, then update our waiting flag */
       
  1269   GST_OBJECT_LOCK (buf);
       
  1270   if (G_UNLIKELY (buf->abidata.ABI.flushing))
       
  1271     goto flushing;
       
  1272 
       
  1273   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
       
  1274           GST_RING_BUFFER_STATE_STARTED))
       
  1275     goto not_started;
       
  1276 
       
  1277   if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
       
  1278     GST_DEBUG_OBJECT (buf, "waiting..");
       
  1279     GST_RING_BUFFER_WAIT (buf);
       
  1280 
       
  1281     if (G_UNLIKELY (buf->abidata.ABI.flushing))
       
  1282       goto flushing;
       
  1283 
       
  1284     if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
       
  1285             GST_RING_BUFFER_STATE_STARTED))
       
  1286       goto not_started;
       
  1287   }
       
  1288   GST_OBJECT_UNLOCK (buf);
       
  1289 
       
  1290   return TRUE;
       
  1291 
       
  1292   /* ERROR */
       
  1293 not_started:
       
  1294   {
       
  1295     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
       
  1296     GST_DEBUG_OBJECT (buf, "stopped processing");
       
  1297     GST_OBJECT_UNLOCK (buf);
       
  1298     return FALSE;
       
  1299   }
       
  1300 flushing:
       
  1301   {
       
  1302     g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0);
       
  1303     GST_DEBUG_OBJECT (buf, "flushing");
       
  1304     GST_OBJECT_UNLOCK (buf);
       
  1305     return FALSE;
       
  1306   }
       
  1307 no_start:
       
  1308   {
       
  1309     GST_DEBUG_OBJECT (buf, "not allowed to start");
       
  1310     return FALSE;
       
  1311   }
       
  1312 }
       
  1313 
       
  1314 #define FWD_SAMPLES(s,se,d,de)		 	\
       
  1315 G_STMT_START {					\
       
  1316   /* no rate conversion */			\
       
  1317   guint towrite = MIN (se + bps - s, de - d);	\
       
  1318   /* simple copy */				\
       
  1319   if (!skip)					\
       
  1320     memcpy (d, s, towrite);			\
       
  1321   in_samples -= towrite / bps;			\
       
  1322   out_samples -= towrite / bps;			\
       
  1323   s += towrite;					\
       
  1324   GST_DEBUG ("copy %u bytes", towrite);		\
       
  1325 } G_STMT_END
       
  1326 
       
  1327 /* in_samples >= out_samples, rate > 1.0 */
       
  1328 #define FWD_UP_SAMPLES(s,se,d,de) 	 	\
       
  1329 G_STMT_START {					\
       
  1330   guint8 *sb = s, *db = d;			\
       
  1331   while (s <= se && d < de) {			\
       
  1332     if (!skip)					\
       
  1333       memcpy (d, s, bps);			\
       
  1334     s += bps;					\
       
  1335     *accum += outr;				\
       
  1336     if ((*accum << 1) >= inr) {			\
       
  1337       *accum -= inr;				\
       
  1338       d += bps;					\
       
  1339     }						\
       
  1340   }						\
       
  1341   in_samples -= (s - sb)/bps;			\
       
  1342   out_samples -= (d - db)/bps;			\
       
  1343   GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess);	\
       
  1344 } G_STMT_END
       
  1345 
       
  1346 /* out_samples > in_samples, for rates smaller than 1.0 */
       
  1347 #define FWD_DOWN_SAMPLES(s,se,d,de) 	 	\
       
  1348 G_STMT_START {					\
       
  1349   guint8 *sb = s, *db = d;			\
       
  1350   while (s <= se && d < de) {			\
       
  1351     if (!skip)					\
       
  1352       memcpy (d, s, bps);			\
       
  1353     d += bps;					\
       
  1354     *accum += inr;				\
       
  1355     if ((*accum << 1) >= outr) {		\
       
  1356       *accum -= outr;				\
       
  1357       s += bps;					\
       
  1358     }						\
       
  1359   }						\
       
  1360   in_samples -= (s - sb)/bps;			\
       
  1361   out_samples -= (d - db)/bps;			\
       
  1362   GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess);	\
       
  1363 } G_STMT_END
       
  1364 
       
  1365 #define REV_UP_SAMPLES(s,se,d,de) 	 	\
       
  1366 G_STMT_START {					\
       
  1367   guint8 *sb = se, *db = d;			\
       
  1368   while (s <= se && d < de) {			\
       
  1369     if (!skip)					\
       
  1370       memcpy (d, se, bps);			\
       
  1371     se -= bps;					\
       
  1372     *accum += outr;				\
       
  1373     while ((*accum << 1) >= inr) {		\
       
  1374       *accum -= inr;				\
       
  1375       d += bps;					\
       
  1376     }						\
       
  1377   }						\
       
  1378   in_samples -= (sb - se)/bps;			\
       
  1379   out_samples -= (d - db)/bps;			\
       
  1380   GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess);	\
       
  1381 } G_STMT_END
       
  1382 
       
  1383 #define REV_DOWN_SAMPLES(s,se,d,de) 	 	\
       
  1384 G_STMT_START {					\
       
  1385   guint8 *sb = se, *db = d;			\
       
  1386   while (s <= se && d < de) {			\
       
  1387     if (!skip)					\
       
  1388       memcpy (d, se, bps);			\
       
  1389     d += bps;					\
       
  1390     *accum += inr;				\
       
  1391     while ((*accum << 1) >= outr) {		\
       
  1392       *accum -= outr;				\
       
  1393       se -= bps;				\
       
  1394     }						\
       
  1395   }						\
       
  1396   in_samples -= (sb - se)/bps;			\
       
  1397   out_samples -= (d - db)/bps;			\
       
  1398   GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess);	\
       
  1399 } G_STMT_END
       
  1400 
       
  1401 /**
       
  1402  * gst_ring_buffer_commit_full:
       
  1403  * @buf: the #GstRingBuffer to commit
       
  1404  * @sample: the sample position of the data
       
  1405  * @data: the data to commit
       
  1406  * @in_samples: the number of samples in the data to commit
       
  1407  * @out_samples: the number of samples to write to the ringbuffer
       
  1408  * @accum: accumulator for rate conversion.
       
  1409  *
       
  1410  * Commit @in_samples samples pointed to by @data to the ringbuffer @buf. 
       
  1411  *
       
  1412  * @in_samples and @out_samples define the rate conversion to perform on the the
       
  1413  * samples in @data. For negative rates, @out_samples must be negative and
       
  1414  * @in_samples positive.
       
  1415  *
       
  1416  * When @out_samples is positive, the first sample will be written at position @sample
       
  1417  * in the ringbuffer. When @out_samples is negative, the last sample will be written to
       
  1418  * @sample in reverse order.
       
  1419  *
       
  1420  * @out_samples does not need to be a multiple of the segment size of the ringbuffer
       
  1421  * although it is recommended for optimal performance. 
       
  1422  *
       
  1423  * @accum will hold a temporary accumulator used in rate conversion and should be
       
  1424  * set to 0 when this function is first called. In case the commit operation is
       
  1425  * interrupted, one can resume the processing by passing the previously returned
       
  1426  * @accum value back to this function.
       
  1427  *
       
  1428  * Returns: The number of samples written to the ringbuffer or -1 on error. The
       
  1429  * number of samples written can be less than @out_samples when @buf was interrupted
       
  1430  * with a flush or stop.
       
  1431  *
       
  1432  * Since: 0.10.11.
       
  1433  *
       
  1434  * MT safe.
       
  1435  */
       
  1436 #ifdef __SYMBIAN32__
       
  1437 EXPORT_C
       
  1438 #endif
       
  1439 
       
  1440 guint
       
  1441 gst_ring_buffer_commit_full (GstRingBuffer * buf, guint64 * sample,
       
  1442     guchar * data, gint in_samples, gint out_samples, gint * accum)
       
  1443 {
       
  1444   gint segdone;
       
  1445   gint segsize, segtotal, bps, sps;
       
  1446   guint8 *dest, *data_end;
       
  1447   gint writeseg, sampleoff;
       
  1448   gint *toprocess;
       
  1449   gint inr, outr;
       
  1450   gboolean reverse;
       
  1451 
       
  1452   if (G_UNLIKELY (in_samples == 0 || out_samples == 0))
       
  1453     return in_samples;
       
  1454 
       
  1455   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
       
  1456   g_return_val_if_fail (buf->data != NULL, -1);
       
  1457   g_return_val_if_fail (data != NULL, -1);
       
  1458 
       
  1459   dest = GST_BUFFER_DATA (buf->data);
       
  1460   segsize = buf->spec.segsize;
       
  1461   segtotal = buf->spec.segtotal;
       
  1462   bps = buf->spec.bytes_per_sample;
       
  1463   sps = buf->samples_per_seg;
       
  1464 
       
  1465   reverse = out_samples < 0;
       
  1466   out_samples = ABS (out_samples);
       
  1467 
       
  1468   if (in_samples >= out_samples)
       
  1469     toprocess = &in_samples;
       
  1470   else
       
  1471     toprocess = &out_samples;
       
  1472 
       
  1473   inr = in_samples - 1;
       
  1474   outr = out_samples - 1;
       
  1475 
       
  1476   /* data_end points to the last sample we have to write, not past it. This is
       
  1477    * needed to properly handle reverse playback: it points to the last sample. */
       
  1478   data_end = data + (bps * inr);
       
  1479 
       
  1480   /* figure out the segment and the offset inside the segment where
       
  1481    * the first sample should be written. */
       
  1482   writeseg = *sample / sps;
       
  1483   sampleoff = (*sample % sps) * bps;
       
  1484 
       
  1485   /* write out all samples */
       
  1486   while (*toprocess > 0) {
       
  1487     gint avail;
       
  1488     guint8 *d, *d_end;
       
  1489     gint ws;
       
  1490     gboolean skip;
       
  1491 
       
  1492     while (TRUE) {
       
  1493       gint diff;
       
  1494 
       
  1495       /* get the currently processed segment */
       
  1496       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
       
  1497 
       
  1498       /* see how far away it is from the write segment */
       
  1499       diff = writeseg - segdone;
       
  1500 
       
  1501       GST_DEBUG
       
  1502           ("pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d",
       
  1503           segdone, writeseg, sampleoff, diff, segtotal, segsize);
       
  1504 
       
  1505       /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */
       
  1506       if (G_UNLIKELY (diff < 0)) {
       
  1507         /* we need to drop one segment at a time, pretend we wrote a
       
  1508          * segment. */
       
  1509         skip = TRUE;
       
  1510         break;
       
  1511       }
       
  1512 
       
  1513       /* write segment is within writable range, we can break the loop and
       
  1514        * start writing the data. */
       
  1515       if (diff < segtotal) {
       
  1516         skip = FALSE;
       
  1517         break;
       
  1518       }
       
  1519 
       
  1520       /* else we need to wait for the segment to become writable. */
       
  1521       if (!wait_segment (buf))
       
  1522         goto not_started;
       
  1523     }
       
  1524 
       
  1525     /* we can write now */
       
  1526     ws = writeseg % segtotal;
       
  1527     avail = MIN (segsize - sampleoff, bps * out_samples);
       
  1528 
       
  1529     d = dest + (ws * segsize) + sampleoff;
       
  1530     d_end = d + avail;
       
  1531     *sample += avail / bps;
       
  1532 
       
  1533     GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
       
  1534         dest + ws * segsize, ws, sps, sampleoff, avail);
       
  1535 
       
  1536     if (G_LIKELY (inr == outr && !reverse)) {
       
  1537       /* no rate conversion, simply copy samples */
       
  1538       FWD_SAMPLES (data, data_end, d, d_end);
       
  1539     } else if (!reverse) {
       
  1540       if (inr >= outr)
       
  1541         /* forward speed up */
       
  1542         FWD_UP_SAMPLES (data, data_end, d, d_end);
       
  1543       else
       
  1544         /* forward slow down */
       
  1545         FWD_DOWN_SAMPLES (data, data_end, d, d_end);
       
  1546     } else {
       
  1547       if (inr >= outr)
       
  1548         /* reverse speed up */
       
  1549         REV_UP_SAMPLES (data, data_end, d, d_end);
       
  1550       else
       
  1551         /* reverse slow down */
       
  1552         REV_DOWN_SAMPLES (data, data_end, d, d_end);
       
  1553     }
       
  1554 
       
  1555     /* for the next iteration we write to the next segment at the beginning. */
       
  1556     writeseg++;
       
  1557     sampleoff = 0;
       
  1558   }
       
  1559   /* we consumed all samples here */
       
  1560   data = data_end + bps;
       
  1561 
       
  1562 done:
       
  1563   return inr - ((data_end - data) / bps);
       
  1564 
       
  1565   /* ERRORS */
       
  1566 not_started:
       
  1567   {
       
  1568     GST_DEBUG_OBJECT (buf, "stopped processing");
       
  1569     goto done;
       
  1570   }
       
  1571 }
       
  1572 
       
  1573 /**
       
  1574  * gst_ring_buffer_commit:
       
  1575  * @buf: the #GstRingBuffer to commit
       
  1576  * @sample: the sample position of the data
       
  1577  * @data: the data to commit
       
  1578  * @len: the number of samples in the data to commit
       
  1579  *
       
  1580  * Same as gst_ring_buffer_commit_full() but with a in_samples and out_samples
       
  1581  * equal to @len, ignoring accum.
       
  1582  *
       
  1583  * Returns: The number of samples written to the ringbuffer or -1 on
       
  1584  * error.
       
  1585  *
       
  1586  * MT safe.
       
  1587  */
       
  1588 #ifdef __SYMBIAN32__
       
  1589 EXPORT_C
       
  1590 #endif
       
  1591 
       
  1592 guint
       
  1593 gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data,
       
  1594     guint len)
       
  1595 {
       
  1596   guint res;
       
  1597   guint64 samplep = sample;
       
  1598 
       
  1599   res = gst_ring_buffer_commit_full (buf, &samplep, data, len, len, NULL);
       
  1600 
       
  1601   return res;
       
  1602 }
       
  1603 
       
  1604 /**
       
  1605  * gst_ring_buffer_read:
       
  1606  * @buf: the #GstRingBuffer to read from
       
  1607  * @sample: the sample position of the data
       
  1608  * @data: where the data should be read
       
  1609  * @len: the number of samples in data to read
       
  1610  *
       
  1611  * Read @len samples from the ringbuffer into the memory pointed 
       
  1612  * to by @data.
       
  1613  * The first sample should be read from position @sample in
       
  1614  * the ringbuffer.
       
  1615  *
       
  1616  * @len should not be a multiple of the segment size of the ringbuffer
       
  1617  * although it is recommended.
       
  1618  *
       
  1619  * Returns: The number of samples read from the ringbuffer or -1 on
       
  1620  * error.
       
  1621  *
       
  1622  * MT safe.
       
  1623  */
       
  1624 #ifdef __SYMBIAN32__
       
  1625 EXPORT_C
       
  1626 #endif
       
  1627 
       
  1628 guint
       
  1629 gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
       
  1630     guint len)
       
  1631 {
       
  1632   gint segdone;
       
  1633   gint segsize, segtotal, bps, sps;
       
  1634   guint8 *dest;
       
  1635   guint to_read;
       
  1636 
       
  1637   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1);
       
  1638   g_return_val_if_fail (buf->data != NULL, -1);
       
  1639   g_return_val_if_fail (data != NULL, -1);
       
  1640 
       
  1641   dest = GST_BUFFER_DATA (buf->data);
       
  1642   segsize = buf->spec.segsize;
       
  1643   segtotal = buf->spec.segtotal;
       
  1644   bps = buf->spec.bytes_per_sample;
       
  1645   sps = buf->samples_per_seg;
       
  1646 
       
  1647   to_read = len;
       
  1648   /* read enough samples */
       
  1649   while (to_read > 0) {
       
  1650     gint sampleslen;
       
  1651     gint readseg, sampleoff;
       
  1652 
       
  1653     /* figure out the segment and the offset inside the segment where
       
  1654      * the sample should be read from. */
       
  1655     readseg = sample / sps;
       
  1656     sampleoff = (sample % sps);
       
  1657 
       
  1658     while (TRUE) {
       
  1659       gint diff;
       
  1660 
       
  1661       /* get the currently processed segment */
       
  1662       segdone = g_atomic_int_get (&buf->segdone) - buf->segbase;
       
  1663 
       
  1664       /* see how far away it is from the read segment, normally segdone (where
       
  1665        * the hardware is writing) is bigger than readseg (where software is
       
  1666        * reading) */
       
  1667       diff = segdone - readseg;
       
  1668 
       
  1669       GST_DEBUG
       
  1670           ("pointer at %d, sample %llu, read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d",
       
  1671           segdone, sample, readseg, sampleoff, to_read, diff, segtotal,
       
  1672           segsize);
       
  1673 
       
  1674       /* segment too far ahead, reader too slow */
       
  1675       if (G_UNLIKELY (diff >= segtotal)) {
       
  1676         /* pretend we read an empty segment. */
       
  1677         sampleslen = MIN (sps, to_read);
       
  1678         memcpy (data, buf->empty_seg, sampleslen * bps);
       
  1679         goto next;
       
  1680       }
       
  1681 
       
  1682       /* read segment is within readable range, we can break the loop and
       
  1683        * start reading the data. */
       
  1684       if (diff > 0)
       
  1685         break;
       
  1686 
       
  1687       /* else we need to wait for the segment to become readable. */
       
  1688       if (!wait_segment (buf))
       
  1689         goto not_started;
       
  1690     }
       
  1691 
       
  1692     /* we can read now */
       
  1693     readseg = readseg % segtotal;
       
  1694     sampleslen = MIN (sps - sampleoff, to_read);
       
  1695 
       
  1696     GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
       
  1697         dest + readseg * segsize, readseg, sampleoff, sampleslen);
       
  1698 
       
  1699     memcpy (data, dest + (readseg * segsize) + (sampleoff * bps),
       
  1700         (sampleslen * bps));
       
  1701 
       
  1702   next:
       
  1703     to_read -= sampleslen;
       
  1704     sample += sampleslen;
       
  1705     data += sampleslen * bps;
       
  1706   }
       
  1707 
       
  1708   return len - to_read;
       
  1709 
       
  1710   /* ERRORS */
       
  1711 not_started:
       
  1712   {
       
  1713     GST_DEBUG_OBJECT (buf, "stopped processing");
       
  1714     return len - to_read;
       
  1715   }
       
  1716 }
       
  1717 
       
  1718 /**
       
  1719  * gst_ring_buffer_prepare_read:
       
  1720  * @buf: the #GstRingBuffer to read from
       
  1721  * @segment: the segment to read
       
  1722  * @readptr: the pointer to the memory where samples can be read
       
  1723  * @len: the number of bytes to read
       
  1724  *
       
  1725  * Returns a pointer to memory where the data from segment @segment
       
  1726  * can be found. This function is mostly used by subclasses.
       
  1727  *
       
  1728  * Returns: FALSE if the buffer is not started.
       
  1729  *
       
  1730  * MT safe.
       
  1731  */
       
  1732 #ifdef __SYMBIAN32__
       
  1733 EXPORT_C
       
  1734 #endif
       
  1735 
       
  1736 gboolean
       
  1737 gst_ring_buffer_prepare_read (GstRingBuffer * buf, gint * segment,
       
  1738     guint8 ** readptr, gint * len)
       
  1739 {
       
  1740   guint8 *data;
       
  1741   gint segdone;
       
  1742 
       
  1743   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
       
  1744 
       
  1745   /* buffer must be started */
       
  1746   if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
       
  1747     return FALSE;
       
  1748 
       
  1749   g_return_val_if_fail (buf->data != NULL, FALSE);
       
  1750   g_return_val_if_fail (segment != NULL, FALSE);
       
  1751   g_return_val_if_fail (readptr != NULL, FALSE);
       
  1752   g_return_val_if_fail (len != NULL, FALSE);
       
  1753 
       
  1754   data = GST_BUFFER_DATA (buf->data);
       
  1755 
       
  1756   /* get the position of the pointer */
       
  1757   segdone = g_atomic_int_get (&buf->segdone);
       
  1758 
       
  1759   *segment = segdone % buf->spec.segtotal;
       
  1760   *len = buf->spec.segsize;
       
  1761   *readptr = data + *segment * *len;
       
  1762 
       
  1763   /* callback to fill the memory with data, for pull based
       
  1764    * scheduling. */
       
  1765   if (buf->callback)
       
  1766     buf->callback (buf, *readptr, *len, buf->cb_data);
       
  1767 
       
  1768   GST_LOG ("prepare read from segment %d (real %d) @%p",
       
  1769       *segment, segdone, *readptr);
       
  1770 
       
  1771   return TRUE;
       
  1772 }
       
  1773 
       
  1774 /**
       
  1775  * gst_ring_buffer_advance:
       
  1776  * @buf: the #GstRingBuffer to advance
       
  1777  * @advance: the number of segments written
       
  1778  *
       
  1779  * Subclasses should call this function to notify the fact that 
       
  1780  * @advance segments are now processed by the device.
       
  1781  *
       
  1782  * MT safe.
       
  1783  */
       
  1784 #ifdef __SYMBIAN32__
       
  1785 EXPORT_C
       
  1786 #endif
       
  1787 
       
  1788 void
       
  1789 gst_ring_buffer_advance (GstRingBuffer * buf, guint advance)
       
  1790 {
       
  1791   g_return_if_fail (GST_IS_RING_BUFFER (buf));
       
  1792 
       
  1793   /* update counter */
       
  1794   g_atomic_int_add (&buf->segdone, advance);
       
  1795 
       
  1796   /* the lock is already taken when the waiting flag is set,
       
  1797    * we grab the lock as well to make sure the waiter is actually
       
  1798    * waiting for the signal */
       
  1799   if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
       
  1800     GST_OBJECT_LOCK (buf);
       
  1801     GST_DEBUG_OBJECT (buf, "signal waiter");
       
  1802     GST_RING_BUFFER_SIGNAL (buf);
       
  1803     GST_OBJECT_UNLOCK (buf);
       
  1804   }
       
  1805 }
       
  1806 
       
  1807 /**
       
  1808  * gst_ring_buffer_clear:
       
  1809  * @buf: the #GstRingBuffer to clear
       
  1810  * @segment: the segment to clear
       
  1811  *
       
  1812  * Clear the given segment of the buffer with silence samples.
       
  1813  * This function is used by subclasses.
       
  1814  *
       
  1815  * MT safe.
       
  1816  */
       
  1817 #ifdef __SYMBIAN32__
       
  1818 EXPORT_C
       
  1819 #endif
       
  1820 
       
  1821 void
       
  1822 gst_ring_buffer_clear (GstRingBuffer * buf, gint segment)
       
  1823 {
       
  1824   guint8 *data;
       
  1825 
       
  1826   g_return_if_fail (GST_IS_RING_BUFFER (buf));
       
  1827 
       
  1828   /* no data means it's already cleared */
       
  1829   if (G_UNLIKELY (buf->data == NULL))
       
  1830     return;
       
  1831 
       
  1832   /* no empty_seg means it's not opened */
       
  1833   if (G_UNLIKELY (buf->empty_seg == NULL))
       
  1834     return;
       
  1835 
       
  1836   segment %= buf->spec.segtotal;
       
  1837 
       
  1838   data = GST_BUFFER_DATA (buf->data);
       
  1839   data += segment * buf->spec.segsize;
       
  1840 
       
  1841   GST_LOG ("clear segment %d @%p", segment, data);
       
  1842 
       
  1843   memcpy (data, buf->empty_seg, buf->spec.segsize);
       
  1844 }
       
  1845 
       
  1846 /**
       
  1847  * gst_ring_buffer_may_start:
       
  1848  * @buf: the #GstRingBuffer
       
  1849  * @allowed: the new value
       
  1850  *
       
  1851  * Tell the ringbuffer that it is allowed to start playback when
       
  1852  * the ringbuffer is filled with samples. 
       
  1853  *
       
  1854  * Since: 0.10.6
       
  1855  *
       
  1856  * MT safe.
       
  1857  */
       
  1858 #ifdef __SYMBIAN32__
       
  1859 EXPORT_C
       
  1860 #endif
       
  1861 
       
  1862 void
       
  1863 gst_ring_buffer_may_start (GstRingBuffer * buf, gboolean allowed)
       
  1864 {
       
  1865   g_return_if_fail (GST_IS_RING_BUFFER (buf));
       
  1866 
       
  1867   GST_LOG_OBJECT (buf, "may start: %d", allowed);
       
  1868   gst_atomic_int_set (&buf->abidata.ABI.may_start, allowed);
       
  1869 }