[xiph-commits] r15893 - in icecast/trunk/ices: . src

karl at svn.xiph.org karl at svn.xiph.org
Tue Mar 31 18:48:13 PDT 2009


Author: karl
Date: 2009-03-31 18:48:13 -0700 (Tue, 31 Mar 2009)
New Revision: 15893

Added:
   icecast/trunk/ices/src/im_roar.c
   icecast/trunk/ices/src/im_roar.h
Modified:
   icecast/trunk/ices/configure.in
   icecast/trunk/ices/src/Makefile.am
   icecast/trunk/ices/src/input.c
Log:
roaraudio input patches by Philipp. closes #1530


Modified: icecast/trunk/ices/configure.in
===================================================================
--- icecast/trunk/ices/configure.in	2009-04-01 01:34:43 UTC (rev 15892)
+++ icecast/trunk/ices/configure.in	2009-04-01 01:48:13 UTC (rev 15893)
@@ -85,6 +85,16 @@
    AC_DEFINE(HAVE_ALSA, ,[Define to enable ALSA input module])
 fi
 
+dnl Check for RoarAudio
+
+AC_CHECK_HEADER(roaraudio.h, have_roaraudio=yes, have_roaraudio=no)
+AM_CONDITIONAL(HAVE_ROARAUDIO,test "$have_roaraudio" = yes)
+
+if test "$have_roaraudio" = yes; then
+   ROARAUDIO_LIBS="-lroar"
+   AC_DEFINE(HAVE_ROARAUDIO, ,[Define to enable RoarAudio input module])
+fi
+
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 
@@ -116,6 +126,7 @@
 dnl Make substitutions
 
 AC_SUBST(ALSA_LIBS)
+AC_SUBST(ROARAUDIO_LIBS)
 AC_SUBST(XML_LIBS)
 AC_SUBST(XML_CFLAGS)
 AC_SUBST(LIBTOOL_DEPS)

Modified: icecast/trunk/ices/src/Makefile.am
===================================================================
--- icecast/trunk/ices/src/Makefile.am	2009-04-01 01:34:43 UTC (rev 15892)
+++ icecast/trunk/ices/src/Makefile.am	2009-04-01 01:48:13 UTC (rev 15893)
@@ -8,7 +8,7 @@
 AM_CPPFLAGS = @XIPH_CPPFLAGS@
 AM_CFLAGS = @XIPH_CFLAGS@
 
-EXTRA_ices_SOURCES = im_oss.c im_sun.c im_alsa.c
+EXTRA_ices_SOURCES = im_oss.c im_sun.c im_alsa.c im_roar.c
 
 if HAVE_OSS
 oss = im_oss.c
@@ -22,14 +22,19 @@
 alsa = im_alsa.c
 endif
 
-dist_noinst_HEADERS = cfgparse.h input.h inputmodule.h im_playlist.h signals.h stream.h reencode.h encode.h playlist_basic.h logging.h im_stdinpcm.h event.h stream_shared.h metadata.h audio.h resample.h im_sun.h im_oss.h im_alsa.h
+if HAVE_ROARAUDIO
+roar = im_roar.c
+endif
 
-ices_SOURCES = input.c cfgparse.c stream.c ices.c signals.c im_playlist.c reencode.c encode.c playlist_basic.c im_stdinpcm.c stream_shared.c metadata.c playlist_script.c audio.c resample.c $(oss) $(sun) $(alsa)
+dist_noinst_HEADERS = cfgparse.h input.h inputmodule.h im_playlist.h signals.h stream.h reencode.h encode.h playlist_basic.h logging.h im_stdinpcm.h event.h stream_shared.h metadata.h audio.h resample.h im_sun.h im_oss.h im_alsa.h im_roar.h
 
+ices_SOURCES = input.c cfgparse.c stream.c ices.c signals.c im_playlist.c reencode.c encode.c playlist_basic.c im_stdinpcm.c stream_shared.c metadata.c playlist_script.c audio.c resample.c $(oss) $(sun) $(alsa) $(roar)
+
 ices_LDADD = log/libicelog.la \
              timing/libicetiming.la \
              thread/libicethread.la \
              avl/libiceavl.la \
+             @ROARAUDIO_LIBS@ \
              @ALSA_LIBS@ @XIPH_LIBS@
 
 debug:

Added: icecast/trunk/ices/src/im_roar.c
===================================================================
--- icecast/trunk/ices/src/im_roar.c	                        (rev 0)
+++ icecast/trunk/ices/src/im_roar.c	2009-04-01 01:48:13 UTC (rev 15893)
@@ -0,0 +1,266 @@
+/* im_oss.c
+ * - Raw PCM/Ogg Vorbis input from RoarAudio
+ *
+ * Copyright (c) 2001 Michael Smith <msmith at labyrinth.net.au>
+ * Copyright (c) 2009 Philipp Schafft <lion at lion.leolix.org>
+ *
+ * This program is distributed under the terms of the GNU General
+ * Public License, version 2. You may use, modify, and redistribute
+ * it under the terms of this license. A copy should be included
+ * with this source.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ogg/ogg.h>
+#include <fcntl.h>
+
+
+#include <thread/thread.h>
+#include "cfgparse.h"
+#include "stream.h"
+#include "metadata.h"
+#include "inputmodule.h"
+
+#include "im_roar.h"
+
+#define MODULE "input-roar/"
+#include "logging.h"
+
+#define BUFSIZE 2048
+
+/* Some platforms (freebsd) don't define this, so just define it to something
+ * that should be treated the same
+ */
+#ifndef ERESTART
+#define ERESTART EINTR
+#endif
+
+static void close_module(input_module_t *mod)
+{
+    if(mod)
+    {
+        if(mod->internal)
+        {
+            im_roar_state *s = mod->internal;
+
+            if(s->fd >= 0)
+                close(s->fd);
+
+
+            thread_mutex_destroy(&s->metadatalock);
+            free(s);
+
+            roar_disconnect(&s->con);
+        }
+        free(mod);
+    }
+}
+
+static int event_handler(input_module_t *mod, enum event_type ev, void *param)
+{
+    im_roar_state *s = mod->internal;
+
+    switch(ev)
+    {
+        case EVENT_SHUTDOWN:
+            close_module(mod);
+            break;
+        case EVENT_NEXTTRACK:
+            s->newtrack = 1;
+            break;
+        case EVENT_METADATAUPDATE:
+            thread_mutex_lock(&s->metadatalock);
+            if(s->metadata)
+            {
+                char **md = s->metadata;
+                while(*md)
+                    free(*md++);
+                free(s->metadata);
+            }
+            s->metadata = (char **)param;
+            s->newtrack = 1;
+            thread_mutex_unlock(&s->metadatalock);
+            break;
+        default:
+            LOG_WARN1("Unhandled event %d", ev);
+            return -1;
+    }
+
+    return 0;
+}
+
+static void metadata_update(void *self, vorbis_comment *vc)
+{
+    im_roar_state *s = self;
+    char **md;
+
+    thread_mutex_lock(&s->metadatalock);
+
+    md = s->metadata;
+
+    if(md)
+    {
+        while(*md)
+            vorbis_comment_add(vc, *md++);
+    }
+
+    thread_mutex_unlock(&s->metadatalock);
+}
+
+/* Core streaming function for this module
+ * This is what actually produces the data which gets streamed.
+ *
+ * returns:  >0  Number of bytes read
+ *            0  Non-fatal error.
+ *           <0  Fatal error.
+ */
+static int roar_read(void *self, ref_buffer *rb)
+{
+    int result;
+    im_roar_state *s = self;
+
+    rb->buf = malloc(BUFSIZE*2*s->channels);
+    if(!rb->buf)
+        return -1;
+
+    result = read(s->fd, rb->buf, BUFSIZE * 2 * s->channels);
+
+    rb->len = result;
+    rb->aux_data = s->rate * s->channels * 2;
+
+    if(s->newtrack)
+    {
+        rb->critical = 1;
+        s->newtrack  = 0;
+    }
+
+    if(result == -1 && (errno == EINTR || errno == ERESTART))
+    {
+        return 0; /* Non-fatal error */
+    }
+    else if(result <= 0)
+    {
+        if(result == 0)
+            LOG_INFO0("Reached EOF, no more data available");
+        else
+            LOG_ERROR1("Error reading from sound server: %s", strerror(errno));
+        free(rb->buf);
+        return -1;
+    }
+
+    return rb->len;
+}
+
+input_module_t *roar_open_module(module_param_t *params)
+{
+    input_module_t *mod = calloc(1, sizeof(input_module_t));
+    im_roar_state *s;
+    module_param_t *current;
+    char * server = NULL;
+    int    codec  = ROAR_CODEC_DEFAULT;
+    int    bits   = 16;
+    int    dir    = ROAR_DIR_MONITOR;
+    int    use_metadata = 1; /* Default to on */
+
+    mod->getdata = roar_read;
+    mod->handle_event = event_handler;
+    mod->metadata_update = metadata_update;
+
+    mod->internal = calloc(1, sizeof(im_roar_state));
+    s = mod->internal;
+
+    s->fd = -1; /* Set it to something invalid, for now */
+    s->rate = 44100; /* Defaults */
+    s->channels = 2; 
+
+    thread_mutex_create(&s->metadatalock);
+
+    current = params;
+
+    while(current)
+    {
+        if(!strcmp(current->name, "rate"))
+            s->rate = atoi(current->value);
+        else if(!strcmp(current->name, "channels"))
+            s->channels = atoi(current->value);
+        else if(!strcmp(current->name, "codec"))
+            codec = roar_str2codec(current->value);
+        else if(!strcmp(current->name, "device"))
+            server = current->value;
+        else if(!strcmp(current->name, "metadata"))
+            use_metadata = atoi(current->value);
+        else if(!strcmp(current->name, "metadatafilename"))
+            ices_config->metadata_filename = current->value;
+        else
+            LOG_WARN1("Unknown parameter %s for roar module", current->name);
+
+        current = current->next;
+    }
+
+    mod->type = ICES_INPUT_PCM;
+
+    switch (codec) {
+        case ROAR_CODEC_PCM_LE:
+          mod->subtype = INPUT_PCM_LE_16;
+         break;
+        case ROAR_CODEC_PCM_BE:
+          mod->subtype = INPUT_PCM_BE_16;
+         break;
+        case ROAR_CODEC_OGG_GENERAL:
+          LOG_WARN0("Codec may not work, specify ogg_vorbis for Vorbis streaming");
+        case ROAR_CODEC_OGG_VORBIS:
+          mod->type = ICES_INPUT_VORBIS;
+          // we do not set mod->subtype here, strange design ices2 has...
+         break;
+        case -1:
+         LOG_ERROR0("Unknown Codec");
+         return NULL;
+        default:
+         LOG_ERROR1("Unsupported Codec: %s", roar_codec2str(codec));
+         return NULL;
+    }
+
+
+    /* First up, lets open the audio device */
+    if ( roar_simple_connect(&s->con, server, "ices2") == -1 ) {
+        LOG_ERROR2("Failed to open sound server %s: %s",
+                server, strerror(errno));
+        goto fail;
+    }
+
+    /* Now, set the required parameters on that device */
+    if ( (s->fd = roar_simple_new_stream_obj(&s->con, &s->stream, s->rate, s->channels, bits, codec, dir)) == -1 ) {
+        LOG_ERROR2("Failed to create a new stream on sound server %s: %s",
+                server, strerror(errno));
+        goto fail;
+    }
+
+    /* We're done, and we didn't fail! */
+    LOG_INFO3("Opened sound server at %s at %d channel(s), %d Hz", 
+            server, s->channels, s->rate);
+
+    if(use_metadata)
+    {
+        LOG_INFO0("Starting metadata update thread");
+        if(ices_config->metadata_filename)
+            thread_create("im_roar-metadata", metadata_thread_signal, mod, 1);
+        else
+            thread_create("im_roar-metadata", metadata_thread_stdin, mod, 1);
+    }
+
+    return mod;
+
+fail:
+    close_module(mod); /* safe, this checks for valid contents */
+    return NULL;
+}
+
+

Added: icecast/trunk/ices/src/im_roar.h
===================================================================
--- icecast/trunk/ices/src/im_roar.h	                        (rev 0)
+++ icecast/trunk/ices/src/im_roar.h	2009-04-01 01:48:13 UTC (rev 15893)
@@ -0,0 +1,36 @@
+/* im_oss.h
+ * - Raw PCM/Ogg Vorbis input from RoarAudio
+ *
+ * Copyright (c) 2001 Michael Smith <msmith at labyrinth.net.au>
+ * Copyright (c) 2009 Philipp Schafft <lion at lion.leolix.org>
+ *
+ * This program is distributed under the terms of the GNU General
+ * Public License, version 2. You may use, modify, and redistribute
+ * it under the terms of this license. A copy should be included
+ * with this source.
+ */
+
+#ifndef __IM_ROAR_H__
+#define __IM_ROAR_H__
+
+#include <thread/thread.h>
+#include <roaraudio.h>
+#include "inputmodule.h"
+
+typedef struct
+{
+    int rate;
+    int channels;
+
+    struct roar_connection con;
+    struct roar_stream     stream;
+
+    int fd;
+    char **metadata;
+    int newtrack;
+    mutex_t metadatalock;
+} im_roar_state; 
+
+input_module_t *roar_open_module(module_param_t *params);
+
+#endif  /* __IM_ROAR_H__ */

Modified: icecast/trunk/ices/src/input.c
===================================================================
--- icecast/trunk/ices/src/input.c	2009-04-01 01:34:43 UTC (rev 15892)
+++ icecast/trunk/ices/src/input.c	2009-04-01 01:48:13 UTC (rev 15893)
@@ -38,6 +38,10 @@
 #include "im_playlist.h"
 #include "im_stdinpcm.h"
 
+#ifdef HAVE_ROARAUDIO
+#include "im_roar.h"
+#endif
+
 #ifdef HAVE_OSS
 #include "im_oss.h"
 #endif
@@ -79,6 +83,9 @@
 static module modules[] = {
     { "playlist", playlist_open_module},
     { "stdinpcm", stdin_open_module},
+#ifdef HAVE_ROARAUDIO
+    { "roar", roar_open_module},
+#endif
 #ifdef HAVE_OSS
     { "oss", oss_open_module},
 #endif



More information about the commits mailing list