tizen 2.0 init
[framework/multimedia/gst-plugins-base0.10.git] / gst-libs / gst / audio / gstaudiosink.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstaudiosink.c: simple audio sink base class
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 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 #include "gst/glib-compat-private.h"
75
76 GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug);
77 #define GST_CAT_DEFAULT gst_audio_sink_debug
78
79 #define GST_TYPE_AUDIORING_BUFFER        \
80         (gst_audioringbuffer_get_type())
81 #define GST_AUDIORING_BUFFER(obj)        \
82         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer))
83 #define GST_AUDIORING_BUFFER_CLASS(klass) \
84         (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass))
85 #define GST_AUDIORING_BUFFER_GET_CLASS(obj) \
86         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass))
87 #define GST_AUDIORING_BUFFER_CAST(obj)        \
88         ((GstAudioRingBuffer *)obj)
89 #define GST_IS_AUDIORING_BUFFER(obj)     \
90         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER))
91 #define GST_IS_AUDIORING_BUFFER_CLASS(klass)\
92         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER))
93
94 typedef struct _GstAudioRingBuffer GstAudioRingBuffer;
95 typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass;
96
97 #define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond)
98 #define GST_AUDIORING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
99 #define GST_AUDIORING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf)))
100 #define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf)))
101
102 struct _GstAudioRingBuffer
103 {
104   GstRingBuffer object;
105
106   gboolean running;
107   gint queuedseg;
108
109   GCond *cond;
110 };
111
112 struct _GstAudioRingBufferClass
113 {
114   GstRingBufferClass parent_class;
115 };
116
117 static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass);
118 static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
119     GstAudioRingBufferClass * klass);
120 static void gst_audioringbuffer_dispose (GObject * object);
121 static void gst_audioringbuffer_finalize (GObject * object);
122
123 static GstRingBufferClass *ring_parent_class = NULL;
124
125 static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf);
126 static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf);
127 static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
128     GstRingBufferSpec * spec);
129 static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
130 static gboolean gst_audioringbuffer_start (GstRingBuffer * buf);
131 static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf);
132 static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
133 static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
134 static gboolean gst_audioringbuffer_activate (GstRingBuffer * buf,
135     gboolean active);
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   GstRingBufferClass *gstringbuffer_class;
169
170   gobject_class = (GObjectClass *) klass;
171   gstringbuffer_class = (GstRingBufferClass *) klass;
172
173   ring_parent_class = g_type_class_peek_parent (klass);
174
175   gobject_class->dispose = gst_audioringbuffer_dispose;
176   gobject_class->finalize = gst_audioringbuffer_finalize;
177
178   gstringbuffer_class->open_device =
179       GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device);
180   gstringbuffer_class->close_device =
181       GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device);
182   gstringbuffer_class->acquire =
183       GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
184   gstringbuffer_class->release =
185       GST_DEBUG_FUNCPTR (gst_audioringbuffer_release);
186   gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
187   gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_audioringbuffer_pause);
188   gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
189   gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
190
191   gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
192   gstringbuffer_class->activate =
193       GST_DEBUG_FUNCPTR (gst_audioringbuffer_activate);
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   GstMessage *message;
211   GValue val = { 0 };
212
213   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
214   csink = GST_AUDIO_SINK_GET_CLASS (sink);
215
216   GST_DEBUG_OBJECT (sink, "enter thread");
217
218   GST_OBJECT_LOCK (abuf);
219   GST_DEBUG_OBJECT (sink, "signal wait");
220   GST_AUDIORING_BUFFER_SIGNAL (buf);
221   GST_OBJECT_UNLOCK (abuf);
222
223   writefunc = csink->write;
224   if (writefunc == NULL)
225     goto no_function;
226
227   g_value_init (&val, G_TYPE_POINTER);
228   g_value_set_pointer (&val, sink->thread);
229   message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
230       GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink));
231   gst_message_set_stream_status_object (message, &val);
232   GST_DEBUG_OBJECT (sink, "posting ENTER stream status");
233   gst_element_post_message (GST_ELEMENT_CAST (sink), message);
234
235   while (TRUE) {
236     gint left, len;
237     guint8 *readptr;
238     gint readseg;
239
240     /* buffer must be started */
241     if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
242       gint written;
243
244       left = len;
245       do {
246         written = writefunc (sink, readptr, left);
247         GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d",
248             written, left, readseg);
249         if (written < 0 || written > left) {
250           /* might not be critical, it e.g. happens when aborting playback */
251           GST_WARNING_OBJECT (sink,
252               "error writing data in %s (reason: %s), skipping segment (left: %d, written: %d)",
253               GST_DEBUG_FUNCPTR_NAME (writefunc),
254               (errno > 1 ? g_strerror (errno) : "unknown"), left, written);
255           break;
256         }
257         left -= written;
258         readptr += written;
259       } while (left > 0);
260
261       /* clear written samples */
262       gst_ring_buffer_clear (buf, readseg);
263
264       /* we wrote one segment */
265       gst_ring_buffer_advance (buf, 1);
266     } else {
267       GST_OBJECT_LOCK (abuf);
268       if (!abuf->running)
269         goto stop_running;
270       if (G_UNLIKELY (g_atomic_int_get (&buf->state) ==
271               GST_RING_BUFFER_STATE_STARTED)) {
272         GST_OBJECT_UNLOCK (abuf);
273         continue;
274       }
275       GST_DEBUG_OBJECT (sink, "signal wait");
276       GST_AUDIORING_BUFFER_SIGNAL (buf);
277       GST_DEBUG_OBJECT (sink, "wait for action");
278       GST_AUDIORING_BUFFER_WAIT (buf);
279       GST_DEBUG_OBJECT (sink, "got signal");
280       if (!abuf->running)
281         goto stop_running;
282       GST_DEBUG_OBJECT (sink, "continue running");
283       GST_OBJECT_UNLOCK (abuf);
284     }
285   }
286
287   /* Will never be reached */
288   g_assert_not_reached ();
289   return;
290
291   /* ERROR */
292 no_function:
293   {
294     GST_DEBUG_OBJECT (sink, "no write function, exit thread");
295     return;
296   }
297 stop_running:
298   {
299     GST_OBJECT_UNLOCK (abuf);
300     GST_DEBUG_OBJECT (sink, "stop running, exit thread");
301     message = gst_message_new_stream_status (GST_OBJECT_CAST (buf),
302         GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (sink));
303     gst_message_set_stream_status_object (message, &val);
304     GST_DEBUG_OBJECT (sink, "posting LEAVE stream status");
305     gst_element_post_message (GST_ELEMENT_CAST (sink), message);
306     return;
307   }
308 }
309
310 static void
311 gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
312     GstAudioRingBufferClass * g_class)
313 {
314   ringbuffer->running = FALSE;
315   ringbuffer->queuedseg = 0;
316
317   ringbuffer->cond = g_cond_new ();
318 }
319
320 static void
321 gst_audioringbuffer_dispose (GObject * object)
322 {
323   G_OBJECT_CLASS (ring_parent_class)->dispose (object);
324 }
325
326 static void
327 gst_audioringbuffer_finalize (GObject * object)
328 {
329   GstAudioRingBuffer *ringbuffer = GST_AUDIORING_BUFFER_CAST (object);
330
331   g_cond_free (ringbuffer->cond);
332
333   G_OBJECT_CLASS (ring_parent_class)->finalize (object);
334 }
335
336 static gboolean
337 gst_audioringbuffer_open_device (GstRingBuffer * buf)
338 {
339   GstAudioSink *sink;
340   GstAudioSinkClass *csink;
341   gboolean result = TRUE;
342
343   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
344   csink = GST_AUDIO_SINK_GET_CLASS (sink);
345
346   if (csink->open)
347     result = csink->open (sink);
348
349   if (!result)
350     goto could_not_open;
351
352   return result;
353
354 could_not_open:
355   {
356     GST_DEBUG_OBJECT (sink, "could not open device");
357     return FALSE;
358   }
359 }
360
361 static gboolean
362 gst_audioringbuffer_close_device (GstRingBuffer * buf)
363 {
364   GstAudioSink *sink;
365   GstAudioSinkClass *csink;
366   gboolean result = TRUE;
367
368   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
369   csink = GST_AUDIO_SINK_GET_CLASS (sink);
370
371   if (csink->close)
372     result = csink->close (sink);
373
374   if (!result)
375     goto could_not_close;
376
377   return result;
378
379 could_not_close:
380   {
381     GST_DEBUG_OBJECT (sink, "could not close device");
382     return FALSE;
383   }
384 }
385
386 static gboolean
387 gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
388 {
389   GstAudioSink *sink;
390   GstAudioSinkClass *csink;
391   gboolean result = FALSE;
392
393   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
394   csink = GST_AUDIO_SINK_GET_CLASS (sink);
395
396   if (csink->prepare)
397     result = csink->prepare (sink, spec);
398   if (!result)
399     goto could_not_prepare;
400
401   /* set latency to one more segment as we need some headroom */
402   spec->seglatency = spec->segtotal + 1;
403
404   buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
405   memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
406
407   return TRUE;
408
409   /* ERRORS */
410 could_not_prepare:
411   {
412     GST_DEBUG_OBJECT (sink, "could not prepare device");
413     return FALSE;
414   }
415 }
416
417 static gboolean
418 gst_audioringbuffer_activate (GstRingBuffer * buf, gboolean active)
419 {
420   GstAudioSink *sink;
421   GstAudioRingBuffer *abuf;
422   GError *error = NULL;
423
424   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
425   abuf = GST_AUDIORING_BUFFER_CAST (buf);
426
427   if (active) {
428     abuf->running = TRUE;
429
430     GST_DEBUG_OBJECT (sink, "starting thread");
431
432 #if !GLIB_CHECK_VERSION (2, 31, 0)
433     sink->thread =
434         g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
435         &error);
436 #else
437     sink->thread = g_thread_try_new ("audiosink-ringbuffer",
438         (GThreadFunc) audioringbuffer_thread_func, buf, &error);
439 #endif
440
441     if (!sink->thread || error != NULL)
442       goto thread_failed;
443
444     GST_DEBUG_OBJECT (sink, "waiting for thread");
445     /* the object lock is taken */
446     GST_AUDIORING_BUFFER_WAIT (buf);
447     GST_DEBUG_OBJECT (sink, "thread is started");
448   } else {
449     abuf->running = FALSE;
450     GST_DEBUG_OBJECT (sink, "signal wait");
451     GST_AUDIORING_BUFFER_SIGNAL (buf);
452
453     GST_OBJECT_UNLOCK (buf);
454
455     /* join the thread */
456     g_thread_join (sink->thread);
457
458     GST_OBJECT_LOCK (buf);
459   }
460   return TRUE;
461
462   /* ERRORS */
463 thread_failed:
464   {
465     if (error)
466       GST_ERROR_OBJECT (sink, "could not create thread %s", error->message);
467     else
468       GST_ERROR_OBJECT (sink, "could not create thread for unknown reason");
469     return FALSE;
470   }
471 }
472
473 /* function is called with LOCK */
474 static gboolean
475 gst_audioringbuffer_release (GstRingBuffer * buf)
476 {
477   GstAudioSink *sink;
478   GstAudioSinkClass *csink;
479   gboolean result = FALSE;
480
481   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
482   csink = GST_AUDIO_SINK_GET_CLASS (sink);
483
484   /* free the buffer */
485   gst_buffer_unref (buf->data);
486   buf->data = NULL;
487
488   if (csink->unprepare)
489     result = csink->unprepare (sink);
490
491   if (!result)
492     goto could_not_unprepare;
493
494   GST_DEBUG_OBJECT (sink, "unprepared");
495
496   return result;
497
498 could_not_unprepare:
499   {
500     GST_DEBUG_OBJECT (sink, "could not unprepare device");
501     return FALSE;
502   }
503 }
504
505 static gboolean
506 gst_audioringbuffer_start (GstRingBuffer * buf)
507 {
508   GstAudioSink *sink;
509
510   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
511
512   GST_DEBUG_OBJECT (sink, "start, sending signal");
513   GST_AUDIORING_BUFFER_SIGNAL (buf);
514
515   return TRUE;
516 }
517
518 static gboolean
519 gst_audioringbuffer_pause (GstRingBuffer * buf)
520 {
521   GstAudioSink *sink;
522   GstAudioSinkClass *csink;
523
524   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
525   csink = GST_AUDIO_SINK_GET_CLASS (sink);
526
527   /* unblock any pending writes to the audio device */
528   if (csink->reset) {
529     GST_DEBUG_OBJECT (sink, "reset...");
530     csink->reset (sink);
531     GST_DEBUG_OBJECT (sink, "reset done");
532   }
533
534   return TRUE;
535 }
536
537 static gboolean
538 gst_audioringbuffer_stop (GstRingBuffer * buf)
539 {
540   GstAudioSink *sink;
541   GstAudioSinkClass *csink;
542
543   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
544   csink = GST_AUDIO_SINK_GET_CLASS (sink);
545
546   /* unblock any pending writes to the audio device */
547   if (csink->reset) {
548     GST_DEBUG_OBJECT (sink, "reset...");
549     csink->reset (sink);
550     GST_DEBUG_OBJECT (sink, "reset done");
551   }
552 #if 0
553   if (abuf->running) {
554     GST_DEBUG_OBJECT (sink, "stop, waiting...");
555     GST_AUDIORING_BUFFER_WAIT (buf);
556     GST_DEBUG_OBJECT (sink, "stopped");
557   }
558 #endif
559
560   return TRUE;
561 }
562
563 static guint
564 gst_audioringbuffer_delay (GstRingBuffer * buf)
565 {
566   GstAudioSink *sink;
567   GstAudioSinkClass *csink;
568   guint res = 0;
569
570   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
571   csink = GST_AUDIO_SINK_GET_CLASS (sink);
572
573   if (csink->delay)
574     res = csink->delay (sink);
575
576   return res;
577 }
578
579 /* AudioSink signals and args */
580 enum
581 {
582   /* FILL ME */
583   LAST_SIGNAL
584 };
585
586 enum
587 {
588   ARG_0,
589 };
590
591 #define _do_init(bla) \
592     GST_DEBUG_CATEGORY_INIT (gst_audio_sink_debug, "audiosink", 0, "audiosink element");
593
594 GST_BOILERPLATE_FULL (GstAudioSink, gst_audio_sink, GstBaseAudioSink,
595     GST_TYPE_BASE_AUDIO_SINK, _do_init);
596
597 static GstRingBuffer *gst_audio_sink_create_ringbuffer (GstBaseAudioSink *
598     sink);
599
600 static void
601 gst_audio_sink_base_init (gpointer g_class)
602 {
603 }
604
605 static void
606 gst_audio_sink_class_init (GstAudioSinkClass * klass)
607 {
608   GstBaseAudioSinkClass *gstbaseaudiosink_class;
609
610   gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
611
612   gstbaseaudiosink_class->create_ringbuffer =
613       GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer);
614
615   g_type_class_ref (GST_TYPE_AUDIORING_BUFFER);
616 }
617
618 static void
619 gst_audio_sink_init (GstAudioSink * audiosink, GstAudioSinkClass * g_class)
620 {
621 }
622
623 static GstRingBuffer *
624 gst_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
625 {
626   GstRingBuffer *buffer;
627
628   GST_DEBUG_OBJECT (sink, "creating ringbuffer");
629   buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL);
630   GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer);
631
632   return buffer;
633 }