source: roaraudio/plugins/gstreamer0.10/roarsink.c @ 2557:d4332b01eb5d

Last change on this file since 2557:d4332b01eb5d was 2557:d4332b01eb5d, checked in by phi, 15 years ago

better formating

File size: 11.1 KB
Line 
1//roarsink.c:
2/* GStreamer
3 * Copyright (C) <2005>      Arwed v. Merkatz <v.merkatz@gmx.net>
4 * Copyright (C) <2008,2009> Philipp 'ph3-der-loewe' Schafft
5 *                            <lion@lion.leolix.org>
6 *
7 * Roughly based on the gstreamer 0.8 esdsink plugin:
8 * Copyright (C) <2001> Richard Boulton <richard-gst@tartarus.org>
9 *
10 * roarsink.c: an RoarAudio audio sink
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 * Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with this library; if not, write to the
24 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 * Boston, MA 02111-1307, USA.
26 */
27
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "roarsink.h"
34#include <unistd.h>
35#include <errno.h>
36
37#define _(x) (x)
38
39//#include <gst/gst-i18n-plugin.h>
40
41#ifndef ROAR_MAX_WRITE_SIZE
42#define ROAR_MAX_WRITE_SIZE (21 * 4096)
43#endif
44#define ROAR_BUF_SIZE 1764 /* this is dynamic for RoarAudio, use the most common value here for the moment */
45
46//GST_DEBUG_CATEGORY_EXTERN (roar_debug);
47//#define GST_CAT_DEFAULT roar_debug
48
49/* elementfactory information */
50static const GstElementDetails roarsink_details =
51GST_ELEMENT_DETAILS("RoarAudio audio sink",
52    "Sink/Audio",
53    "Plays audio to an RoarAudio server",
54    "Philipp 'ph3-der-loewe' Schafft <lion@lion.leolix.org>");
55
56enum
57{
58  PROP_0,
59  PROP_HOST
60};
61
62static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE("sink",
63    GST_PAD_SINK,
64    GST_PAD_ALWAYS,
65    GST_STATIC_CAPS("audio/x-raw-int, "
66        "endianness = (int) BYTE_ORDER, "
67        "signed = (boolean) TRUE, "
68        "width = (int) 16, "
69        "depth = (int) 16, "
70        "rate = (int) [ 1, MAX ], "
71        "channels = (int) [ 1, 2 ]; "
72
73        "audio/x-raw-int, "
74        "signed = (boolean) { true, false }, "
75        "width = (int) 8, "
76        "depth = (int) 8, "
77        "rate = (int) [ 1, MAX ], "
78        "channels = (int) [ 1, 2 ]"
79       )
80    );
81
82static void gst_roarsink_finalize (GObject * object);
83
84static GstCaps *gst_roarsink_getcaps (GstBaseSink * bsink);
85
86static gboolean gst_roarsink_open (GstAudioSink * asink);
87static gboolean gst_roarsink_close (GstAudioSink * asink);
88static gboolean gst_roarsink_prepare (GstAudioSink * asink,
89    GstRingBufferSpec * spec);
90static gboolean gst_roarsink_unprepare (GstAudioSink * asink);
91static guint gst_roarsink_write (GstAudioSink * asink, gpointer data,
92    guint length);
93static guint gst_roarsink_delay (GstAudioSink * asink);
94static void gst_roarsink_reset (GstAudioSink * asink);
95
96static void gst_roarsink_set_property (GObject * object, guint prop_id,
97    const GValue * value, GParamSpec * pspec);
98static void gst_roarsink_get_property (GObject * object, guint prop_id,
99    GValue * value, GParamSpec * pspec);
100
101GST_BOILERPLATE (GstRoarSink, gst_roarsink, GstAudioSink, GST_TYPE_AUDIO_SINK);
102
103static void gst_roarsink_base_init (gpointer g_class) {
104  GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
105
106  gst_element_class_add_pad_template(element_class,
107      gst_static_pad_template_get(&sink_factory));
108  gst_element_class_set_details(element_class, &roarsink_details);
109}
110
111static void gst_roarsink_class_init (GstRoarSinkClass * klass) {
112  GObjectClass *gobject_class;
113  GstBaseSinkClass *gstbasesink_class;
114  GstBaseAudioSinkClass *gstbaseaudiosink_class;
115  GstAudioSinkClass *gstaudiosink_class;
116
117  gobject_class          = (GObjectClass *) klass;
118  gstbasesink_class      = (GstBaseSinkClass *) klass;
119  gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
120  gstaudiosink_class     = (GstAudioSinkClass *) klass;
121
122  parent_class = g_type_class_peek_parent(klass);
123
124  gobject_class->finalize = gst_roarsink_finalize;
125
126  gstbasesink_class->get_caps   = GST_DEBUG_FUNCPTR(gst_roarsink_getcaps);
127
128  gstaudiosink_class->open      = GST_DEBUG_FUNCPTR(gst_roarsink_open);
129  gstaudiosink_class->close     = GST_DEBUG_FUNCPTR(gst_roarsink_close);
130  gstaudiosink_class->prepare   = GST_DEBUG_FUNCPTR(gst_roarsink_prepare);
131  gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR(gst_roarsink_unprepare);
132  gstaudiosink_class->write     = GST_DEBUG_FUNCPTR(gst_roarsink_write);
133  gstaudiosink_class->delay     = GST_DEBUG_FUNCPTR(gst_roarsink_delay);
134  gstaudiosink_class->reset     = GST_DEBUG_FUNCPTR(gst_roarsink_reset);
135
136  gobject_class->set_property   = gst_roarsink_set_property;
137  gobject_class->get_property   = gst_roarsink_get_property;
138
139  /* default value is filled in the _init method */
140  g_object_class_install_property(gobject_class, PROP_HOST,
141      g_param_spec_string("host", "Host",
142          "The host running the RoarAudio daemon", NULL, G_PARAM_READWRITE));
143}
144
145static void gst_roarsink_init (GstRoarSink * roarsink, GstRoarSinkClass * klass) {
146  memset(&(roarsink->con), 0, sizeof(roarsink->con));
147  roar_connect_fh(&(roarsink->con), -1);
148  roarsink->fd     = -1;
149  roarsink->host   = NULL;
150}
151
152static void gst_roarsink_finalize (GObject * object) {
153  GstRoarSink *roarsink = GST_ROARSINK(object);
154
155  gst_caps_replace(&roarsink->cur_caps, NULL);
156  if ( roarsink->host != NULL )
157   g_free(roarsink->host);
158
159  G_OBJECT_CLASS(parent_class)->finalize(object);
160}
161
162static GstCaps * gst_roarsink_getcaps (GstBaseSink * bsink) {
163  GstRoarSink *roarsink;
164
165  roarsink = GST_ROARSINK(bsink);
166
167  /* no fd, we're done with the template caps */
168  if (roar_get_connection_fh(&(roarsink->con)) < 0 || roarsink->cur_caps == NULL) {
169    GST_LOG_OBJECT(roarsink, "getcaps called, returning template caps");
170    return NULL;
171  }
172
173  GST_LOG_OBJECT(roarsink, "returning %" GST_PTR_FORMAT, roarsink->cur_caps);
174
175  return gst_caps_ref(roarsink->cur_caps);
176}
177
178static gboolean gst_roarsink_open(GstAudioSink * asink) {
179  GstPadTemplate *pad_template;
180  GstRoarSink *roarsink;
181  gint i;
182  struct roar_stream oinfo;
183
184  roarsink = GST_ROARSINK(asink);
185
186  GST_DEBUG_OBJECT(roarsink, "open");
187
188  /* now try to connect to any existing/running sound daemons */
189  if ( roar_simple_connect(&(roarsink->con), roarsink->host, "gstreamer client") == -1 )
190    goto couldnt_connect;
191
192  /* get server info */
193  if ( roar_server_oinfo(&(roarsink->con), &oinfo) == -1 )
194    goto no_server_info;
195
196  GST_INFO_OBJECT(roarsink, "got server info rate: %i", oinfo.info.rate);
197
198  pad_template = gst_static_pad_template_get(&sink_factory);
199  roarsink->cur_caps = gst_caps_copy(gst_pad_template_get_caps(pad_template));
200
201  for (i = 0; i < roarsink->cur_caps->structs->len; i++) {
202    GstStructure *s;
203
204    s = gst_caps_get_structure(roarsink->cur_caps, i);
205    gst_structure_set(s, "rate", G_TYPE_INT, oinfo.info.rate, NULL);
206  }
207
208  GST_INFO_OBJECT(roarsink, "server caps: %" GST_PTR_FORMAT, roarsink->cur_caps);
209
210  return TRUE;
211
212  /* ERRORS */
213couldnt_connect:
214  {
215    GST_ELEMENT_ERROR(roarsink, RESOURCE, OPEN_WRITE,
216        (_("Could not establish connection to sound server")),
217        ("can't open connection to esound server"));
218    return FALSE;
219  }
220no_server_info:
221  {
222    GST_ELEMENT_ERROR(roarsink, RESOURCE, OPEN_WRITE,
223        (_("Failed to query sound server capabilities")),
224        ("couldn't get server info!"));
225    return FALSE;
226  }
227}
228
229static gboolean gst_roarsink_close (GstAudioSink * asink) {
230  GstRoarSink *roarsink = GST_ROARSINK(asink);
231
232  GST_DEBUG_OBJECT(roarsink, "close");
233
234  gst_caps_replace(&roarsink->cur_caps, NULL);
235
236  roar_disconnect(&(roarsink->con));
237
238  if ( roarsink->fd != -1 )
239   close(roarsink->fd);
240
241  return TRUE;
242}
243
244static gboolean gst_roarsink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) {
245  GstRoarSink *roarsink = GST_ROARSINK(asink);
246
247  GST_DEBUG_OBJECT(roarsink, "prepare");
248
249 
250  GST_INFO_OBJECT(roarsink, "attempting to open data connection to esound server");
251
252  roarsink->fd = roar_simple_new_stream(&(roarsink->con), spec->rate, spec->channels, spec->depth,
253                                        ROAR_CODEC_DEFAULT, ROAR_DIR_PLAY);
254
255  if ( roarsink->fd == -1 )
256    goto cannot_open;
257
258  roarsink->rate = spec->rate;
259
260  spec->segsize  = ROAR_BUF_SIZE;
261  spec->segtotal = (ROAR_MAX_WRITE_SIZE / spec->segsize);
262
263  /* FIXME: this is wrong for signed ints (and the
264   * audioringbuffers should do it for us anyway) */
265  spec->silence_sample[0] = 0;
266  spec->silence_sample[1] = 0;
267  spec->silence_sample[2] = 0;
268  spec->silence_sample[3] = 0;
269
270  GST_INFO_OBJECT(roarsink, "successfully opened connection to esound server");
271
272  return TRUE;
273
274  /* ERRORS */
275cannot_open:
276  {
277    GST_ELEMENT_ERROR(roarsink, RESOURCE, OPEN_WRITE,
278        (_("Could not establish connection to sound server")),
279        ("can't open connection to RoarAudio server"));
280    return FALSE;
281  }
282}
283
284static gboolean gst_roarsink_unprepare (GstAudioSink * asink) {
285  GstRoarSink *roarsink = GST_ROARSINK(asink);
286
287  if ((roarsink->fd == -1) && (roar_get_connection_fh(&(roarsink->con)) == -1))
288    return TRUE;
289
290  close(roarsink->fd);
291  roarsink->fd = -1;
292
293  GST_INFO_OBJECT(roarsink, "closed sound device");
294
295  return TRUE;
296}
297
298
299static guint gst_roarsink_write (GstAudioSink * asink, gpointer data, guint length) {
300  GstRoarSink *roarsink = GST_ROARSINK(asink);
301  gint to_write = 0;
302
303  to_write = length;
304
305  while (to_write > 0) {
306    int done;
307
308    done = write(roarsink->fd, data, to_write);
309
310    if (done < 0)
311      goto write_error;
312
313    to_write -= done;
314    data += done;
315  }
316  return length;
317
318  /* ERRORS */
319write_error:
320  {
321    GST_ELEMENT_ERROR(roarsink, RESOURCE, WRITE,
322        ("Failed to write data to the RoarAudio daemon"), GST_ERROR_SYSTEM);
323    return 0;
324  }
325}
326
327static guint gst_roarsink_delay (GstAudioSink * asink) {
328//  GstRoarSink *roarsink = GST_ROARSINK (asink);
329  guint latency;
330
331  latency = 441; // compile type depending and link level deppendent,
332                 // use default value for local operations here for the moment
333
334  GST_DEBUG_OBJECT(asink, "got latency: %u", latency);
335
336  return latency;
337}
338
339static void gst_roarsink_reset (GstAudioSink * asink) {
340  GST_DEBUG_OBJECT(asink, "reset called");
341}
342
343static void gst_roarsink_set_property (GObject * object, guint prop_id, const GValue * value,
344                                       GParamSpec * pspec) {
345  GstRoarSink *roarsink = GST_ROARSINK(object);
346
347  switch (prop_id) {
348    case PROP_HOST:
349      if ( roarsink->host != NULL )
350       g_free(roarsink->host);
351      roarsink->host = g_value_dup_string(value);
352     break;
353    default:
354      break;
355  }
356}
357
358static void gst_roarsink_get_property (GObject * object, guint prop_id, GValue * value,
359                                       GParamSpec * pspec) {
360  GstRoarSink *roarsink = GST_ROARSINK(object);
361
362  switch (prop_id) {
363    case PROP_HOST:
364      g_value_set_string(value, roarsink->host);
365     break;
366    default:
367      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
368     break;
369  }
370}
371
372gboolean gst_roarsink_factory_init (GstPlugin * plugin) {
373  if (!gst_element_register(plugin, "roarsink", GST_RANK_MARGINAL,
374                            GST_TYPE_ROARSINK))
375    return FALSE;
376
377  return TRUE;
378}
Note: See TracBrowser for help on using the repository browser.