expand tabs
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstaudiosink.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstaudiosink.c: simple audio sink base class
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <string.h>
24
25 #include "gstaudiosink.h"
26
27 GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug);
28 #define GST_CAT_DEFAULT gst_audio_sink_debug
29
30 #define GST_TYPE_AUDIORING_BUFFER        \
31         (gst_audioringbuffer_get_type())
32 #define GST_AUDIORING_BUFFER(obj)        \
33         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer))
34 #define GST_AUDIORING_BUFFER_CLASS(klass) \
35         (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass))
36 #define GST_AUDIORING_BUFFER_GET_CLASS(obj) \
37         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass))
38 #define GST_IS_AUDIORING_BUFFER(obj)     \
39         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER))
40 #define GST_IS_AUDIORING_BUFFER_CLASS(obj)\
41         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER))
42
43 typedef struct _GstAudioRingBuffer GstAudioRingBuffer;
44 typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass;
45
46 #define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond)
47 #define GST_AUDIORING_BUFFER_WAIT(buf)     (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf)))
48 #define GST_AUDIORING_BUFFER_SIGNAL(buf)   (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf)))
49 #define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf)))
50
51 struct _GstAudioRingBuffer
52 {
53   GstRingBuffer object;
54
55   gboolean running;
56   gint queuedseg;
57
58   GCond *cond;
59 };
60
61 struct _GstAudioRingBufferClass
62 {
63   GstRingBufferClass parent_class;
64 };
65
66 static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass);
67 static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
68     GstAudioRingBufferClass * klass);
69 static void gst_audioringbuffer_dispose (GObject * object);
70 static void gst_audioringbuffer_finalize (GObject * object);
71
72 static GstRingBufferClass *ring_parent_class = NULL;
73
74 static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf);
75 static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf);
76 static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
77     GstRingBufferSpec * spec);
78 static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
79 static gboolean gst_audioringbuffer_start (GstRingBuffer * buf);
80 static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf);
81 static guint gst_audioringbuffer_delay (GstRingBuffer * buf);
82
83 /* ringbuffer abstract base class */
84 static GType
85 gst_audioringbuffer_get_type (void)
86 {
87   static GType ringbuffer_type = 0;
88
89   if (!ringbuffer_type) {
90     static const GTypeInfo ringbuffer_info = {
91       sizeof (GstAudioRingBufferClass),
92       NULL,
93       NULL,
94       (GClassInitFunc) gst_audioringbuffer_class_init,
95       NULL,
96       NULL,
97       sizeof (GstAudioRingBuffer),
98       0,
99       (GInstanceInitFunc) gst_audioringbuffer_init,
100       NULL
101     };
102
103     ringbuffer_type =
104         g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSinkRingBuffer",
105         &ringbuffer_info, 0);
106   }
107   return ringbuffer_type;
108 }
109
110 static void
111 gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass)
112 {
113   GObjectClass *gobject_class;
114   GstObjectClass *gstobject_class;
115   GstRingBufferClass *gstringbuffer_class;
116
117   gobject_class = (GObjectClass *) klass;
118   gstobject_class = (GstObjectClass *) klass;
119   gstringbuffer_class = (GstRingBufferClass *) klass;
120
121   ring_parent_class = g_type_class_ref (GST_TYPE_RING_BUFFER);
122
123   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_audioringbuffer_dispose);
124   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_audioringbuffer_finalize);
125
126   gstringbuffer_class->open_device =
127       GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device);
128   gstringbuffer_class->close_device =
129       GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device);
130   gstringbuffer_class->acquire =
131       GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
132   gstringbuffer_class->release =
133       GST_DEBUG_FUNCPTR (gst_audioringbuffer_release);
134   gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
135   gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
136   gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start);
137   gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop);
138
139   gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay);
140 }
141
142 typedef guint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length);
143
144 /* this internal thread does nothing else but write samples to the audio device.
145  * It will write each segment in the ringbuffer and will update the play
146  * pointer. 
147  * The start/stop methods control the thread.
148  */
149 static void
150 audioringbuffer_thread_func (GstRingBuffer * buf)
151 {
152   GstAudioSink *sink;
153   GstAudioSinkClass *csink;
154   GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER (buf);
155   WriteFunc writefunc;
156
157   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
158   csink = GST_AUDIO_SINK_GET_CLASS (sink);
159
160   GST_DEBUG ("enter thread");
161
162   writefunc = csink->write;
163   if (writefunc == NULL)
164     goto no_function;
165
166   while (TRUE) {
167     gint left, len;
168     guint8 *readptr;
169     gint readseg;
170
171     if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
172       gint written = 0;
173
174       left = len;
175       do {
176         written = writefunc (sink, readptr + written, left);
177         GST_LOG ("transfered %d bytes of %d from segment %d", written, left,
178             readseg);
179         if (written < 0 || written > left) {
180           GST_WARNING ("error writing data (reason: %s), skipping segment\n",
181               strerror (errno));
182           break;
183         }
184         left -= written;
185       } while (left > 0);
186
187       /* clear written samples */
188       gst_ring_buffer_clear (buf, readseg);
189
190       /* we wrote one segment */
191       gst_ring_buffer_advance (buf, 1);
192     } else {
193       GST_OBJECT_LOCK (abuf);
194       if (!abuf->running)
195         goto stop_running;
196       GST_DEBUG ("signal wait");
197       GST_AUDIORING_BUFFER_SIGNAL (buf);
198       GST_DEBUG ("wait for action");
199       GST_AUDIORING_BUFFER_WAIT (buf);
200       GST_DEBUG ("got signal");
201       if (!abuf->running)
202         goto stop_running;
203       GST_DEBUG ("continue running");
204       GST_OBJECT_UNLOCK (abuf);
205     }
206   }
207   GST_DEBUG ("exit thread");
208
209   return;
210
211   /* ERROR */
212 no_function:
213   {
214     GST_DEBUG ("no write function, exit thread");
215     return;
216   }
217 stop_running:
218   {
219     GST_OBJECT_UNLOCK (abuf);
220     GST_DEBUG ("stop running, exit thread");
221     return;
222   }
223 }
224
225 static void
226 gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer,
227     GstAudioRingBufferClass * g_class)
228 {
229   ringbuffer->running = FALSE;
230   ringbuffer->queuedseg = 0;
231
232   ringbuffer->cond = g_cond_new ();
233 }
234
235 static void
236 gst_audioringbuffer_dispose (GObject * object)
237 {
238   G_OBJECT_CLASS (ring_parent_class)->dispose (object);
239 }
240
241 static void
242 gst_audioringbuffer_finalize (GObject * object)
243 {
244   G_OBJECT_CLASS (ring_parent_class)->finalize (object);
245 }
246
247 static gboolean
248 gst_audioringbuffer_open_device (GstRingBuffer * buf)
249 {
250   GstAudioSink *sink;
251   GstAudioSinkClass *csink;
252   gboolean result = TRUE;
253
254   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
255   csink = GST_AUDIO_SINK_GET_CLASS (sink);
256
257   if (csink->open)
258     result = csink->open (sink);
259
260   if (!result)
261     goto could_not_open;
262
263   return result;
264
265 could_not_open:
266   {
267     GST_DEBUG ("could not open device");
268     return FALSE;
269   }
270 }
271
272 static gboolean
273 gst_audioringbuffer_close_device (GstRingBuffer * buf)
274 {
275   GstAudioSink *sink;
276   GstAudioSinkClass *csink;
277   gboolean result = TRUE;
278
279   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
280   csink = GST_AUDIO_SINK_GET_CLASS (sink);
281
282   if (csink->close)
283     result = csink->close (sink);
284
285   if (!result)
286     goto could_not_close;
287
288   return result;
289
290 could_not_close:
291   {
292     GST_DEBUG ("could not close device");
293     return FALSE;
294   }
295 }
296
297 static gboolean
298 gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
299 {
300   GstAudioSink *sink;
301   GstAudioSinkClass *csink;
302   GstAudioRingBuffer *abuf;
303   gboolean result = FALSE;
304
305   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
306   csink = GST_AUDIO_SINK_GET_CLASS (sink);
307
308   if (csink->prepare)
309     result = csink->prepare (sink, spec);
310
311   if (!result)
312     goto could_not_prepare;
313
314   /* allocate one more segment as we need some headroom */
315   spec->segtotal++;
316
317   buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
318   memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
319
320   abuf = GST_AUDIORING_BUFFER (buf);
321   abuf->running = TRUE;
322
323   sink->thread =
324       g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE,
325       NULL);
326   GST_AUDIORING_BUFFER_WAIT (buf);
327
328   return result;
329
330 could_not_prepare:
331   {
332     GST_DEBUG ("could not prepare device");
333     return FALSE;
334   }
335 }
336
337 /* function is called with LOCK */
338 static gboolean
339 gst_audioringbuffer_release (GstRingBuffer * buf)
340 {
341   GstAudioSink *sink;
342   GstAudioSinkClass *csink;
343   GstAudioRingBuffer *abuf;
344   gboolean result = FALSE;
345
346   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
347   csink = GST_AUDIO_SINK_GET_CLASS (sink);
348   abuf = GST_AUDIORING_BUFFER (buf);
349
350   abuf->running = FALSE;
351   GST_AUDIORING_BUFFER_SIGNAL (buf);
352   GST_OBJECT_UNLOCK (buf);
353
354   /* join the thread */
355   g_thread_join (sink->thread);
356
357   GST_OBJECT_LOCK (buf);
358
359   /* free the buffer */
360   gst_buffer_unref (buf->data);
361   buf->data = NULL;
362
363   if (csink->unprepare)
364     result = csink->unprepare (sink);
365
366   if (!result)
367     goto could_not_unprepare;
368
369   return result;
370
371 could_not_unprepare:
372   {
373     GST_DEBUG ("could not unprepare device");
374     return FALSE;
375   }
376 }
377
378 static gboolean
379 gst_audioringbuffer_start (GstRingBuffer * buf)
380 {
381   GstAudioSink *sink;
382
383   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
384
385   GST_DEBUG ("start, sending signal");
386   GST_AUDIORING_BUFFER_SIGNAL (buf);
387
388   return TRUE;
389 }
390
391 static gboolean
392 gst_audioringbuffer_stop (GstRingBuffer * buf)
393 {
394   GstAudioSink *sink;
395   GstAudioSinkClass *csink;
396   GstAudioRingBuffer *abuf;
397
398   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
399   csink = GST_AUDIO_SINK_GET_CLASS (sink);
400   abuf = GST_AUDIORING_BUFFER (buf);
401
402   /* unblock any pending writes to the audio device */
403   if (csink->reset) {
404     GST_DEBUG ("reset...");
405     csink->reset (sink);
406     GST_DEBUG ("reset done");
407   }
408
409   if (abuf->running) {
410     GST_DEBUG ("stop, waiting...");
411     GST_AUDIORING_BUFFER_WAIT (buf);
412     GST_DEBUG ("stopped");
413   }
414
415   return TRUE;
416 }
417
418 static guint
419 gst_audioringbuffer_delay (GstRingBuffer * buf)
420 {
421   GstAudioSink *sink;
422   GstAudioSinkClass *csink;
423   guint res = 0;
424
425   sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf));
426   csink = GST_AUDIO_SINK_GET_CLASS (sink);
427
428   if (csink->delay)
429     res = csink->delay (sink);
430
431   return res;
432 }
433
434 /* AudioSink signals and args */
435 enum
436 {
437   /* FILL ME */
438   LAST_SIGNAL
439 };
440
441 enum
442 {
443   ARG_0,
444 };
445
446 #define _do_init(bla) \
447     GST_DEBUG_CATEGORY_INIT (gst_audio_sink_debug, "audiosink", 0, "audiosink element");
448
449 GST_BOILERPLATE_FULL (GstAudioSink, gst_audio_sink, GstBaseAudioSink,
450     GST_TYPE_BASE_AUDIO_SINK, _do_init);
451
452 static GstRingBuffer *gst_audio_sink_create_ringbuffer (GstBaseAudioSink *
453     sink);
454
455 static void
456 gst_audio_sink_base_init (gpointer g_class)
457 {
458 }
459
460 static void
461 gst_audio_sink_class_init (GstAudioSinkClass * klass)
462 {
463   GObjectClass *gobject_class;
464   GstElementClass *gstelement_class;
465   GstBaseSinkClass *gstbasesink_class;
466   GstBaseAudioSinkClass *gstbaseaudiosink_class;
467
468   gobject_class = (GObjectClass *) klass;
469   gstelement_class = (GstElementClass *) klass;
470   gstbasesink_class = (GstBaseSinkClass *) klass;
471   gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
472
473   gstbaseaudiosink_class->create_ringbuffer =
474       GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer);
475 }
476
477 static void
478 gst_audio_sink_init (GstAudioSink * audiosink, GstAudioSinkClass * g_class)
479 {
480 }
481
482 static GstRingBuffer *
483 gst_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
484 {
485   GstRingBuffer *buffer;
486
487   GST_DEBUG ("creating ringbuffer");
488   buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL);
489   GST_DEBUG ("created ringbuffer @%p", buffer);
490
491   return buffer;
492 }