4fc420072358e77f33c8887c0c13a72d97e3a38b
[platform/upstream/gst-plugins-good.git] / ext / shout2 / gstshout2.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "gstshout2.h"
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "gst/gst-i18n-plugin.h"
30
31 GST_DEBUG_CATEGORY_STATIC (shout2_debug);
32 #define GST_CAT_DEFAULT shout2_debug
33
34 static const GstElementDetails shout2send_details =
35 GST_ELEMENT_DETAILS ("Icecast network sink",
36     "Sink/Network",
37     "Sends data to an icecast server",
38     "Wim Taymans <wim.taymans@chello.be>\n"
39     "Pedro Corte-Real <typo@netcabo.pt>\n"
40     "Zaheer Abbas Merali <zaheerabbas at merali dot org>");
41
42
43 enum
44 {
45   SIGNAL_CONNECTION_PROBLEM,    /* 0.11 FIXME: remove this */
46   LAST_SIGNAL
47 };
48
49 enum
50 {
51   ARG_0,
52   ARG_IP,                       /* the ip of the server */
53   ARG_PORT,                     /* the encoder port number on the server */
54   ARG_PASSWORD,                 /* the encoder password on the server */
55   ARG_PUBLIC,                   /* is this stream public? */
56   ARG_STREAMNAME,               /* Name of the stream */
57   ARG_DESCRIPTION,              /* Description of the stream */
58   ARG_GENRE,                    /* Genre of the stream */
59
60   ARG_PROTOCOL,                 /* Protocol to connect with */
61
62   ARG_MOUNT,                    /* mountpoint of stream (icecast only) */
63   ARG_URL                       /* Url of stream (I'm guessing) */
64 };
65
66 #define DEFAULT_IP           "127.0.0.1"
67 #define DEFAULT_PORT         8000
68 #define DEFAULT_PASSWORD     "hackme"
69 #define DEFAULT_STREAMNAME   ""
70 #define DEFAULT_DESCRIPTION  ""
71 #define DEFAULT_GENRE        ""
72 #define DEFAULT_MOUNT        ""
73 #define DEFAULT_URL          ""
74 #define DEFAULT_PROTOCOL     SHOUT2SEND_PROTOCOL_HTTP
75
76 static GstElementClass *parent_class = NULL;
77
78 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
79     GST_PAD_SINK,
80     GST_PAD_ALWAYS,
81     GST_STATIC_CAPS ("application/ogg; "
82         "audio/mpeg, mpegversion = (int) 1, layer = (int) [ 1, 3 ]")
83     );
84 static void gst_shout2send_class_init (GstShout2sendClass * klass);
85 static void gst_shout2send_base_init (GstShout2sendClass * klass);
86 static void gst_shout2send_init (GstShout2send * shout2send);
87
88 static gboolean gst_shout2send_event (GstBaseSink * sink, GstEvent * event);
89 static GstFlowReturn gst_shout2send_render (GstBaseSink * sink,
90     GstBuffer * buffer);
91 static gboolean gst_shout2send_start (GstBaseSink * basesink);
92 static gboolean gst_shout2send_stop (GstBaseSink * basesink);
93
94 static void gst_shout2send_set_property (GObject * object, guint prop_id,
95     const GValue * value, GParamSpec * pspec);
96 static void gst_shout2send_get_property (GObject * object, guint prop_id,
97     GValue * value, GParamSpec * pspec);
98
99 static gboolean gst_shout2send_setcaps (GstPad * pad, GstCaps * caps);
100
101 static guint gst_shout2send_signals[LAST_SIGNAL] = { 0 };
102
103 #define GST_TYPE_SHOUT_PROTOCOL (gst_shout2send_protocol_get_type())
104 static GType
105 gst_shout2send_protocol_get_type (void)
106 {
107   static GType shout2send_protocol_type = 0;
108   static GEnumValue shout2send_protocol[] = {
109     {SHOUT2SEND_PROTOCOL_XAUDIOCAST,
110         "Xaudiocast Protocol (icecast 1.3.x)", "xaudiocast"},
111     {SHOUT2SEND_PROTOCOL_ICY, "Icy Protocol (ShoutCast)", "icy"},
112     {SHOUT2SEND_PROTOCOL_HTTP, "Http Protocol (icecast 2.x)", "http"},
113     {0, NULL, NULL},
114   };
115
116   if (!shout2send_protocol_type) {
117     shout2send_protocol_type =
118         g_enum_register_static ("GstShout2SendProtocol", shout2send_protocol);
119   }
120
121
122   return shout2send_protocol_type;
123 }
124
125 GType
126 gst_shout2send_get_type (void)
127 {
128   static GType shout2send_type = 0;
129
130   if (!shout2send_type) {
131     static const GTypeInfo shout2send_info = {
132       sizeof (GstShout2sendClass),
133       (GBaseInitFunc) gst_shout2send_base_init,
134       NULL,
135       (GClassInitFunc) gst_shout2send_class_init,
136       NULL,
137       NULL,
138       sizeof (GstShout2send),
139       0,
140       (GInstanceInitFunc) gst_shout2send_init,
141     };
142
143     static const GInterfaceInfo tag_setter_info = {
144       NULL,
145       NULL,
146       NULL
147     };
148
149     shout2send_type =
150         g_type_register_static (GST_TYPE_BASE_SINK, "GstShout2send",
151         &shout2send_info, 0);
152
153     g_type_add_interface_static (shout2send_type, GST_TYPE_TAG_SETTER,
154         &tag_setter_info);
155
156   }
157   return shout2send_type;
158 }
159
160 static void
161 gst_shout2send_base_init (GstShout2sendClass * klass)
162 {
163   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
164
165   gst_element_class_add_pad_template (element_class,
166       gst_static_pad_template_get (&sink_template));
167   gst_element_class_set_details (element_class, &shout2send_details);
168
169   GST_DEBUG_CATEGORY_INIT (shout2_debug, "shout2", 0, "shout2send element");
170 }
171
172 static void
173 gst_shout2send_class_init (GstShout2sendClass * klass)
174 {
175   GObjectClass *gobject_class;
176   GstBaseSinkClass *gstbasesink_class;
177
178   gobject_class = (GObjectClass *) klass;
179   gstbasesink_class = (GstBaseSinkClass *) klass;
180
181   parent_class = g_type_class_peek_parent (klass);
182
183   gobject_class->set_property = gst_shout2send_set_property;
184   gobject_class->get_property = gst_shout2send_get_property;
185
186   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_IP,
187       g_param_spec_string ("ip", "ip", "ip", DEFAULT_IP, G_PARAM_READWRITE));
188   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PORT,
189       g_param_spec_int ("port", "port", "port", 1, G_MAXUSHORT, DEFAULT_PORT,
190           G_PARAM_READWRITE));
191
192   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PASSWORD,
193       g_param_spec_string ("password", "password", "password", DEFAULT_PASSWORD,
194           G_PARAM_READWRITE));
195
196   /* metadata */
197   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STREAMNAME,
198       g_param_spec_string ("streamname", "streamname", "name of the stream",
199           DEFAULT_STREAMNAME, G_PARAM_READWRITE));
200
201   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DESCRIPTION,
202       g_param_spec_string ("description", "description", "description",
203           DEFAULT_DESCRIPTION, G_PARAM_READWRITE));
204
205   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GENRE,
206       g_param_spec_string ("genre", "genre", "genre", DEFAULT_GENRE,
207           G_PARAM_READWRITE));
208
209   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PROTOCOL,
210       g_param_spec_enum ("protocol", "protocol", "Connection Protocol to use",
211           GST_TYPE_SHOUT_PROTOCOL, DEFAULT_PROTOCOL, G_PARAM_READWRITE));
212
213
214   /* icecast only */
215   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MOUNT,
216       g_param_spec_string ("mount", "mount", "mount", DEFAULT_MOUNT,
217           G_PARAM_READWRITE));
218
219   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_URL,
220       g_param_spec_string ("url", "url", "url", DEFAULT_URL,
221           G_PARAM_READWRITE));
222
223   /* signals */
224   gst_shout2send_signals[SIGNAL_CONNECTION_PROBLEM] =
225       g_signal_new ("connection-problem", G_TYPE_FROM_CLASS (klass),
226       G_SIGNAL_RUN_CLEANUP, G_STRUCT_OFFSET (GstShout2sendClass,
227           connection_problem), NULL, NULL, g_cclosure_marshal_VOID__INT,
228       G_TYPE_NONE, 1, G_TYPE_INT);
229
230   gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_shout2send_start);
231   gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_shout2send_stop);
232   gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_shout2send_render);
233   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_shout2send_event);
234 }
235
236 static void
237 gst_shout2send_init (GstShout2send * shout2send)
238 {
239   gst_base_sink_set_sync (GST_BASE_SINK (shout2send), FALSE);
240
241   gst_pad_set_setcaps_function (GST_BASE_SINK_PAD (shout2send),
242       GST_DEBUG_FUNCPTR (gst_shout2send_setcaps));
243
244   shout2send->ip = g_strdup (DEFAULT_IP);
245   shout2send->port = DEFAULT_PORT;
246   shout2send->password = g_strdup (DEFAULT_PASSWORD);
247   shout2send->streamname = g_strdup (DEFAULT_STREAMNAME);
248   shout2send->description = g_strdup (DEFAULT_DESCRIPTION);
249   shout2send->genre = g_strdup (DEFAULT_GENRE);
250   shout2send->mount = g_strdup (DEFAULT_MOUNT);
251   shout2send->url = g_strdup (DEFAULT_URL);
252   shout2send->protocol = DEFAULT_PROTOCOL;
253
254   shout2send->tags = gst_tag_list_new ();
255   shout2send->conn = NULL;
256   shout2send->audio_format = SHOUT_FORMAT_VORBIS;
257   shout2send->connected = FALSE;
258   shout2send->songmetadata = NULL;
259 }
260
261 static void
262 set_shout_metadata (const GstTagList * list, const gchar * tag,
263     gpointer user_data)
264 {
265   char **shout_metadata = (char **) user_data;
266   gchar *value, *temp;
267
268   GST_DEBUG ("tag: %s being added", tag);
269   if (strcmp (tag, GST_TAG_ARTIST) == 0) {
270     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
271       if (!gst_tag_list_get_string (list, tag, &value)) {
272         GST_DEBUG ("Error reading \"%s\" tag value", tag);
273         return;
274       }
275       /* shout_metadata should be NULL if title is after artist in  list */
276       if (*shout_metadata == NULL) {
277         *shout_metadata = g_strdup (value);
278       } else {
279         temp = g_strdup_printf ("%s - %s", value, *shout_metadata);
280         g_free (*shout_metadata);
281         *shout_metadata = temp;
282       }
283
284     }
285   } else if (strcmp (tag, GST_TAG_TITLE) == 0) {
286     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
287       if (!gst_tag_list_get_string (list, tag, &value)) {
288         GST_DEBUG ("Error reading \"%s\" tag value", tag);
289         return;
290       }
291       /* shout_metadata should be NULL if title is before artist in  list */
292       if (*shout_metadata == NULL) {
293         *shout_metadata = g_strdup (value);
294       } else {
295         temp = g_strdup_printf ("%s - %s", *shout_metadata, value);
296         g_free (*shout_metadata);
297         *shout_metadata = temp;
298       }
299     }
300   }
301   GST_LOG ("shout metadata is now: %s", *shout_metadata);
302 }
303
304 #if 0
305 static void
306 gst_shout2send_set_metadata (GstShout2send * shout2send)
307 {
308   const GstTagList *user_tags;
309   GstTagList *copy;
310   char *tempmetadata;
311   shout_metadata_t *pmetadata;
312
313   g_return_if_fail (shout2send != NULL);
314   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (shout2send));
315   if ((shout2send->tags == NULL) && (user_tags == NULL)) {
316     return;
317   }
318   copy = gst_tag_list_merge (user_tags, shout2send->tags,
319       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (shout2send)));
320   /* lets get the artist and song tags */
321   tempmetadata = NULL;
322   gst_tag_list_foreach ((GstTagList *) copy, set_shout_metadata,
323       (gpointer) & tempmetadata);
324   if (tempmetadata) {
325     pmetadata = shout_metadata_new ();
326     shout_metadata_add (pmetadata, "song", tempmetadata);
327     shout_set_metadata (shout2send->conn, pmetadata);
328     shout_metadata_free (pmetadata);
329   }
330
331   gst_tag_list_free (copy);
332 }
333 #endif
334
335
336 static gboolean
337 gst_shout2send_event (GstBaseSink * sink, GstEvent * event)
338 {
339   GstShout2send *shout2send;
340   gboolean ret = TRUE;
341
342   shout2send = GST_SHOUT2SEND (sink);
343
344   GST_LOG_OBJECT (shout2send, "got %s event", GST_EVENT_TYPE_NAME (event));
345
346   switch (GST_EVENT_TYPE (event)) {
347     case GST_EVENT_TAG:{
348       /* vorbis audio doesnt need metadata setting on the icecast level, only mp3 */
349       if (shout2send->tags && shout2send->audio_format == SHOUT_FORMAT_MP3) {
350         GstTagList *list;
351
352         gst_event_parse_tag (event, &list);
353         GST_DEBUG_OBJECT (shout2send, "tags=%" GST_PTR_FORMAT, list);
354         gst_tag_list_insert (shout2send->tags,
355             list,
356             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (shout2send)));
357         /* lets get the artist and song tags */
358         gst_tag_list_foreach ((GstTagList *) shout2send->tags,
359             set_shout_metadata, &shout2send->songmetadata);
360         if (shout2send->songmetadata && shout2send->connected) {
361           shout_metadata_t *pmetadata;
362
363           GST_DEBUG_OBJECT (shout2send, "metadata now: %s",
364               shout2send->songmetadata);
365
366           pmetadata = shout_metadata_new ();
367           shout_metadata_add (pmetadata, "song", shout2send->songmetadata);
368           shout_set_metadata (shout2send->conn, pmetadata);
369           shout_metadata_free (pmetadata);
370         }
371       }
372       break;
373     }
374     default:{
375       GST_LOG_OBJECT (shout2send, "let base class handle event");
376       if (GST_BASE_SINK_CLASS (parent_class)->event) {
377         event = gst_event_ref (event);
378         ret = GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
379       }
380       break;
381     }
382   }
383
384   return ret;
385 }
386
387 static gboolean
388 gst_shout2send_start (GstBaseSink * basesink)
389 {
390   GstShout2send *sink = GST_SHOUT2SEND (basesink);
391   const gchar *cur_prop;
392   gshort proto = 3;
393   gchar *version_string;
394
395   GST_DEBUG_OBJECT (sink, "starting");
396
397   sink->conn = shout_new ();
398
399   switch (sink->protocol) {
400     case SHOUT2SEND_PROTOCOL_XAUDIOCAST:
401       proto = SHOUT_PROTOCOL_XAUDIOCAST;
402       break;
403     case SHOUT2SEND_PROTOCOL_ICY:
404       proto = SHOUT_PROTOCOL_ICY;
405       break;
406     case SHOUT2SEND_PROTOCOL_HTTP:
407       proto = SHOUT_PROTOCOL_HTTP;
408       break;
409   }
410
411   cur_prop = "protocol";
412   GST_DEBUG_OBJECT (sink, "setting protocol: %d", sink->protocol);
413   if (shout_set_protocol (sink->conn, proto) != SHOUTERR_SUCCESS)
414     goto set_failed;
415
416   /* --- FIXME: shout requires an ip, and fails if it is given a host. */
417   /* may want to put convert_to_ip(shout2send->ip) here */
418   cur_prop = "ip";
419   GST_DEBUG_OBJECT (sink, "setting ip: %s", sink->ip);
420   if (shout_set_host (sink->conn, sink->ip) != SHOUTERR_SUCCESS)
421     goto set_failed;
422
423   cur_prop = "port";
424   GST_DEBUG_OBJECT (sink, "setting port: %u", sink->port);
425   if (shout_set_port (sink->conn, sink->port) != SHOUTERR_SUCCESS)
426     goto set_failed;
427
428   cur_prop = "password";
429   GST_DEBUG_OBJECT (sink, "setting password: %s", sink->password);
430   if (shout_set_password (sink->conn, sink->password) != SHOUTERR_SUCCESS)
431     goto set_failed;
432
433   cur_prop = "streamname";
434   GST_DEBUG_OBJECT (sink, "setting %s: %s", cur_prop, sink->streamname);
435   if (shout_set_name (sink->conn, sink->streamname) != SHOUTERR_SUCCESS)
436     goto set_failed;
437
438   cur_prop = "description";
439   GST_DEBUG_OBJECT (sink, "setting %s: %s", cur_prop, sink->description);
440   if (shout_set_description (sink->conn, sink->description) != SHOUTERR_SUCCESS)
441     goto set_failed;
442
443   cur_prop = "genre";
444   GST_DEBUG_OBJECT (sink, "setting %s: %s", cur_prop, sink->genre);
445   if (shout_set_genre (sink->conn, sink->genre) != SHOUTERR_SUCCESS)
446     goto set_failed;
447
448   cur_prop = "mount";
449   GST_DEBUG_OBJECT (sink, "setting %s: %s", cur_prop, sink->mount);
450   if (shout_set_mount (sink->conn, sink->mount) != SHOUTERR_SUCCESS)
451     goto set_failed;
452
453   cur_prop = "user";
454   GST_DEBUG_OBJECT (sink, "setting %s: %s", cur_prop, "source");
455   if (shout_set_user (sink->conn, "source") != SHOUTERR_SUCCESS)
456     goto set_failed;
457
458   version_string = gst_version_string ();
459   cur_prop = "agent";
460   GST_DEBUG_OBJECT (sink, "setting %s: %s", cur_prop, version_string);
461   if (shout_set_agent (sink->conn, version_string) != SHOUTERR_SUCCESS) {
462     g_free (version_string);
463     goto set_failed;
464   }
465
466   g_free (version_string);
467   return TRUE;
468
469 /* ERROR */
470 set_failed:
471   {
472     GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
473         ("Error setting %s: %s", cur_prop, shout_get_error (sink->conn)));
474     return FALSE;
475   }
476 }
477
478 static gboolean
479 gst_shout2send_connect (GstShout2send * sink)
480 {
481   GST_DEBUG_OBJECT (sink, "Connection format is: %s",
482       (sink->audio_format == SHOUT_FORMAT_VORBIS) ? "vorbis" :
483       ((sink->audio_format == SHOUT_FORMAT_MP3) ? "mp3" : "unknown"));
484
485   if (shout_set_format (sink->conn, sink->audio_format) != SHOUTERR_SUCCESS)
486     goto could_not_set_format;
487
488   if (shout_open (sink->conn) != SHOUTERR_SUCCESS)
489     goto could_not_connect;
490
491   GST_DEBUG_OBJECT (sink, "connected to server");
492   sink->connected = TRUE;
493
494   /* let's set metadata */
495   if (sink->songmetadata) {
496     shout_metadata_t *pmetadata;
497
498     GST_DEBUG_OBJECT (sink, "shout metadata now: %s", sink->songmetadata);
499     pmetadata = shout_metadata_new ();
500     shout_metadata_add (pmetadata, "song", sink->songmetadata);
501     shout_set_metadata (sink->conn, pmetadata);
502     shout_metadata_free (pmetadata);
503   }
504
505   return TRUE;
506
507 /* ERRORS */
508 could_not_set_format:
509   {
510     GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
511         ("Error setting connection format: %s", shout_get_error (sink->conn)));
512     return FALSE;
513   }
514
515 could_not_connect:
516   {
517     GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
518         (_("Could not connect to server")),
519         ("shout_open() failed: err=%s", shout_get_error (sink->conn)));
520     g_signal_emit (sink, gst_shout2send_signals[SIGNAL_CONNECTION_PROBLEM], 0,
521         shout_get_errno (sink->conn));
522     return FALSE;
523   }
524 }
525
526 static gboolean
527 gst_shout2send_stop (GstBaseSink * basesink)
528 {
529   GstShout2send *sink = GST_SHOUT2SEND (basesink);
530
531   if (sink->conn) {
532     if (sink->connected)
533       shout_close (sink->conn);
534     shout_free (sink->conn);
535     sink->conn = NULL;
536   }
537
538   if (sink->songmetadata) {
539     g_free (sink->songmetadata);
540     sink->songmetadata = NULL;
541   }
542
543   sink->connected = FALSE;
544
545   return TRUE;
546 }
547
548 static GstFlowReturn
549 gst_shout2send_render (GstBaseSink * basesink, GstBuffer * buf)
550 {
551   GstShout2send *sink;
552   glong ret;
553
554   sink = GST_SHOUT2SEND (basesink);
555
556   /* presumably we connect here because we need to know the format before
557    * we can set up the connection, which we don't know yet in _start() */
558   if (!sink->connected) {
559     if (!gst_shout2send_connect (sink))
560       return GST_FLOW_ERROR;
561   }
562
563   /* FIXME: do we want to do syncing here at all? (tpm) */
564   /* GST_LOG_OBJECT (sink, "using libshout to sync"); */
565   shout_sync (sink->conn);
566
567   GST_LOG_OBJECT (sink, "sending %u bytes of data", GST_BUFFER_SIZE (buf));
568   ret = shout_send (sink->conn, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
569   if (ret != SHOUTERR_SUCCESS)
570     goto send_error;
571
572   return GST_FLOW_OK;
573
574 /* ERRORS */
575 send_error:
576   {
577     GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
578         ("shout_send() failed: %s", shout_get_error (sink->conn)));
579     g_signal_emit (sink, gst_shout2send_signals[SIGNAL_CONNECTION_PROBLEM], 0,
580         shout_get_errno (sink->conn));
581     return GST_FLOW_ERROR;
582   }
583 }
584
585 static void
586 gst_shout2send_set_property (GObject * object, guint prop_id,
587     const GValue * value, GParamSpec * pspec)
588 {
589   GstShout2send *shout2send;
590
591   shout2send = GST_SHOUT2SEND (object);
592   switch (prop_id) {
593
594     case ARG_IP:
595       if (shout2send->ip)
596         g_free (shout2send->ip);
597       shout2send->ip = g_strdup (g_value_get_string (value));
598       break;
599     case ARG_PORT:
600       shout2send->port = g_value_get_int (value);
601       break;
602     case ARG_PASSWORD:
603       if (shout2send->password)
604         g_free (shout2send->password);
605       shout2send->password = g_strdup (g_value_get_string (value));
606       break;
607     case ARG_STREAMNAME:       /* Name of the stream */
608       if (shout2send->streamname)
609         g_free (shout2send->streamname);
610       shout2send->streamname = g_strdup (g_value_get_string (value));
611       break;
612     case ARG_DESCRIPTION:      /* Description of the stream */
613       if (shout2send->description)
614         g_free (shout2send->description);
615       shout2send->description = g_strdup (g_value_get_string (value));
616       break;
617     case ARG_GENRE:            /* Genre of the stream */
618       if (shout2send->genre)
619         g_free (shout2send->genre);
620       shout2send->genre = g_strdup (g_value_get_string (value));
621       break;
622     case ARG_PROTOCOL:         /* protocol to connect with */
623       shout2send->protocol = g_value_get_enum (value);
624       break;
625     case ARG_MOUNT:            /* mountpoint of stream (icecast only) */
626       if (shout2send->mount)
627         g_free (shout2send->mount);
628       shout2send->mount = g_strdup (g_value_get_string (value));
629       break;
630     case ARG_URL:              /* Url of the stream (I'm guessing) */
631       if (shout2send->url)
632         g_free (shout2send->url);
633       shout2send->url = g_strdup (g_value_get_string (value));
634       break;
635     default:
636       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
637       break;
638   }
639 }
640
641 static void
642 gst_shout2send_get_property (GObject * object, guint prop_id,
643     GValue * value, GParamSpec * pspec)
644 {
645   GstShout2send *shout2send;
646
647   shout2send = GST_SHOUT2SEND (object);
648   switch (prop_id) {
649
650     case ARG_IP:
651       g_value_set_string (value, shout2send->ip);
652       break;
653     case ARG_PORT:
654       g_value_set_int (value, shout2send->port);
655       break;
656     case ARG_PASSWORD:
657       g_value_set_string (value, shout2send->password);
658       break;
659     case ARG_STREAMNAME:       /* Name of the stream */
660       g_value_set_string (value, shout2send->streamname);
661       break;
662     case ARG_DESCRIPTION:      /* Description of the stream */
663       g_value_set_string (value, shout2send->description);
664       break;
665     case ARG_GENRE:            /* Genre of the stream */
666       g_value_set_string (value, shout2send->genre);
667       break;
668     case ARG_PROTOCOL:         /* protocol to connect with */
669       g_value_set_enum (value, shout2send->protocol);
670       break;
671     case ARG_MOUNT:            /* mountpoint of stream (icecast only) */
672       g_value_set_string (value, shout2send->mount);
673       break;
674     case ARG_URL:              /* Url of stream (I'm guessing) */
675       g_value_set_string (value, shout2send->url);
676       break;
677     default:
678       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
679       break;
680   }
681 }
682
683 static gboolean
684 gst_shout2send_setcaps (GstPad * pad, GstCaps * caps)
685 {
686   const gchar *mimetype;
687   GstShout2send *shout2send;
688   gboolean ret = TRUE;
689
690   shout2send = GST_SHOUT2SEND (GST_OBJECT_PARENT (pad));
691
692   mimetype = gst_structure_get_name (gst_caps_get_structure (caps, 0));
693
694   GST_DEBUG_OBJECT (shout2send, "mimetype of caps given is: %s", mimetype);
695
696   if (!strcmp (mimetype, "audio/mpeg")) {
697     shout2send->audio_format = SHOUT_FORMAT_MP3;
698   } else if (!strcmp (mimetype, "application/ogg")) {
699     shout2send->audio_format = SHOUT_FORMAT_VORBIS;
700   } else {
701     ret = FALSE;
702   }
703
704   return ret;
705 }
706
707 static gboolean
708 plugin_init (GstPlugin * plugin)
709 {
710 #ifdef ENABLE_NLS
711   setlocale (LC_ALL, "");
712   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
713 #endif /* ENABLE_NLS */
714
715   return gst_element_register (plugin, "shout2send", GST_RANK_NONE,
716       GST_TYPE_SHOUT2SEND);
717 }
718
719 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
720     GST_VERSION_MINOR,
721     "shout2send",
722     "Sends data to an icecast server using libshout2",
723     plugin_init,
724     VERSION, "LGPL", "libshout2", "http://www.icecast.org/download.html")