diff --git a/Makefile.am b/Makefile.am index e100965b..c56a9be0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,7 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src conf debian doc web admin win32 EXTRA_DIST = HACKING m4/acx_pthread.m4 m4/ogg.m4 \ - m4/theora.m4 m4/vorbis.m4 \ + m4/theora.m4 m4/vorbis.m4 m4/speex.m4 \ m4/xiph_compiler.m4 m4/xiph_curl.m4 m4/xiph_net.m4 \ m4/xiph_types.m4 m4/xiph_xml2.m4 icecast.spec diff --git a/configure.in b/configure.in index 84649be5..09fa79ed 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT([Icecast], [2.2.0], [icecast@xiph.org]) +AC_INIT([Icecast], [2.2.0-trunk], [icecast@xiph.org]) AC_PREREQ(2.54) AC_CONFIG_SRCDIR(src/main.c) @@ -91,6 +91,16 @@ XIPH_PATH_THEORA([ [ AC_MSG_WARN([Theora disabled!]) ]) +XIPH_PATH_SPEEX( + [ XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$SPEEX_CFLAGS]) + XIPH_VAR_PREPEND([XIPH_LIBS],[$SPEEX_LIBS]) + XIPH_VAR_APPEND([XIPH_LDFLAGS],[$SPEEX_LDFLAGS]) + ICECAST_OPTIONAL="$ICECAST_OPTIONAL format_speex.o" + ], + [ AC_MSG_WARN([Speex support disabled!]) + ]) + + ACX_PTHREAD(, AC_MSG_ERROR([POSIX threads missing])) XIPH_VAR_APPEND([XIPH_CFLAGS],[$PTHREAD_CFLAGS]) XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$PTHREAD_CPPFLAGS]) diff --git a/src/Makefile.am b/src/Makefile.am index fcfe680e..492c5242 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,12 +10,13 @@ noinst_HEADERS = admin.h cfgfile.h os.h logging.h sighandler.h connection.h \ global.h util.h slave.h source.h stats.h refbuf.h client.h format.h \ compat.h format_mp3.h fserve.h xslt.h yp.h event.h md5.h \ auth.h format_ogg.h \ - format_vorbis.h format_theora.h + format_vorbis.h format_theora.h format_flac.h format_speex.h icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c \ - util.c slave.c source.c stats.c refbuf.c client.c format.c format_ogg.c \ - format_mp3.c xslt.c fserve.c event.c admin.c auth.c md5.c + util.c slave.c source.c stats.c refbuf.c client.c \ + xslt.c fserve.c event.c admin.c auth.c md5.c \ + format.c format_ogg.c format_mp3.c format_midi.c format_flac.c EXTRA_icecast_SOURCES = yp.c \ - format_vorbis.c format_theora.c + format_vorbis.c format_theora.c format_speex.c icecast_DEPENDENCIES = @ICECAST_OPTIONAL@ net/libicenet.la thread/libicethread.la \ httpp/libicehttpp.la log/libicelog.la avl/libiceavl.la timing/libicetiming.la diff --git a/src/format_flac.c b/src/format_flac.c new file mode 100644 index 00000000..0b55cb4c --- /dev/null +++ b/src/format_flac.c @@ -0,0 +1,126 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2000-2004, Jack Moffitt , + * oddsock , + * Karl Heyes + * and others (see AUTHORS for details). + */ + + +/* Ogg codec handler for FLAC logical streams */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +typedef struct source_tag source_t; + +#include "refbuf.h" +#include "format_ogg.h" +#include "client.h" +#include "stats.h" + +#define CATMODULE "format-flac" +#include "logging.h" + + +static void flac_codec_free (ogg_state_t *ogg_info, ogg_codec_t *codec) +{ + DEBUG0 ("freeing FLAC codec"); + stats_event (ogg_info->mount, "FLAC_version", NULL); + ogg_stream_clear (&codec->os); + free (codec); +} + + +/* Here, we just verify the page is ok and then add it to the queue */ +static refbuf_t *process_flac_page (ogg_state_t *ogg_info, ogg_codec_t *codec, ogg_page *page) +{ + refbuf_t * refbuf; + + if (ogg_stream_pagein (&codec->os, page) < 0) + { + ogg_info->error = 1; + return NULL; + } + if (codec->headers) + { + ogg_packet packet; + while (ogg_stream_packetout (&codec->os, &packet)) + { + int type = packet.packet[0]; + if (type == 0xFF) + { + codec->headers = 0; + break; + } + if (type >= 1 && type <= 0x7E) + continue; + if (type >= 0x81 && type <= 0xFE) + continue; + ogg_info->error = 1; + return NULL; + } + if (codec->headers) + { + format_ogg_attach_header (ogg_info, page); + return NULL; + } + } + refbuf = make_refbuf_with_page (page); + return refbuf; +} + + +/* Check for flac header in logical stream */ + +ogg_codec_t *initial_flac_page (format_plugin_t *plugin, ogg_page *page) +{ + ogg_state_t *ogg_info = plugin->_state; + ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t)); + ogg_packet packet; + + ogg_stream_init (&codec->os, ogg_page_serialno (page)); + ogg_stream_pagein (&codec->os, page); + + ogg_stream_packetout (&codec->os, &packet); + + DEBUG0("checking for FLAC codec"); + do + { + unsigned char *parse = packet.packet; + + if (page->header_len + page->body_len != 79) + break; + if (*parse != 0x7F) + break; + parse++; + if (memcmp (parse, "FLAC", 4) != 0) + break; + + INFO0 ("seen initial FLAC header"); + + parse += 4; + stats_event_args (ogg_info->mount, "FLAC_version", "%d.%d", parse[0], parse[1]); + codec->process_page = process_flac_page; + codec->codec_free = flac_codec_free; + codec->headers = 1; + codec->name = "FLAC"; + + format_ogg_attach_header (ogg_info, page); + return codec; + } while (0); + + ogg_stream_clear (&codec->os); + free (codec); + return NULL; +} + diff --git a/src/format_flac.h b/src/format_flac.h new file mode 100644 index 00000000..377e7710 --- /dev/null +++ b/src/format_flac.h @@ -0,0 +1,21 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2000-2004, Jack Moffitt , + * oddsock , + * Karl Heyes + * and others (see AUTHORS for details). + */ + + +#ifndef __FORMAT_FLAC_H +#define __FORMAT_FLAC_H + +#include "format_ogg.h" + +ogg_codec_t *initial_flac_page (format_plugin_t *plugin, ogg_page *page); + +#endif /* __FORMAT_FLAC_H */ diff --git a/src/format_midi.c b/src/format_midi.c new file mode 100644 index 00000000..070416fe --- /dev/null +++ b/src/format_midi.c @@ -0,0 +1,95 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2000-2004, Jack Moffitt , + * oddsock , + * Karl Heyes + * and others (see AUTHORS for details). + */ + + +/* Ogg codec handler for MIDI logical streams */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +typedef struct source_tag source_t; + +#include "refbuf.h" +#include "format_ogg.h" +#include "client.h" +#include "stats.h" + +#define CATMODULE "format-midi" +#include "logging.h" + + +static void midi_codec_free (ogg_state_t *ogg_info, ogg_codec_t *codec) +{ + DEBUG0 ("freeing MIDI codec"); + ogg_stream_clear (&codec->os); + free (codec); +} + + +/* Here, we just verify the page is ok and then add it to the queue */ +static refbuf_t *process_midi_page (ogg_state_t *ogg_info, ogg_codec_t *codec, ogg_page *page) +{ + refbuf_t * refbuf; + + if (ogg_stream_pagein (&codec->os, page) < 0) + { + ogg_info->error = 1; + return NULL; + } + refbuf = make_refbuf_with_page (page); + return refbuf; +} + + +/* Check for midi header in logical stream */ + +ogg_codec_t *initial_midi_page (format_plugin_t *plugin, ogg_page *page) +{ + ogg_state_t *ogg_info = plugin->_state; + ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t)); + ogg_packet packet; + + ogg_stream_init (&codec->os, ogg_page_serialno (page)); + ogg_stream_pagein (&codec->os, page); + + ogg_stream_packetout (&codec->os, &packet); + + DEBUG0("checking for MIDI codec"); + do + { + if (packet.bytes < 9) + break; + if (memcmp (packet.packet, "OggMIDI\000", 8) != 0) + break; + if (packet.bytes != 12) + break; + + INFO0 ("seen initial MIDI header"); + codec->process_page = process_midi_page; + codec->codec_free = midi_codec_free; + codec->headers = 1; + codec->name = "MIDI"; + + format_ogg_attach_header (ogg_info, page); + return codec; + } while (0); + + ogg_stream_clear (&codec->os); + free (codec); + return NULL; +} + diff --git a/src/format_midi.h b/src/format_midi.h new file mode 100644 index 00000000..28a40df8 --- /dev/null +++ b/src/format_midi.h @@ -0,0 +1,21 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2000-2004, Jack Moffitt , + * oddsock , + * Karl Heyes + * and others (see AUTHORS for details). + */ + + +#ifndef __FORMAT_MIDI_H +#define __FORMAT_MIDI_H + +#include "format_ogg.h" + +ogg_codec_t *initial_midi_page (format_plugin_t *plugin, ogg_page *page); + +#endif /* __FORMAT_MIDI_H */ diff --git a/src/format_ogg.c b/src/format_ogg.c index 4c98c9d6..3d69c93a 100644 --- a/src/format_ogg.c +++ b/src/format_ogg.c @@ -37,6 +37,11 @@ #ifdef HAVE_THEORA #include "format_theora.h" #endif +#ifdef HAVE_SPEEX +#include "format_speex.h" +#endif +#include "format_midi.h" +#include "format_flac.h" #ifdef _WIN32 #define snprintf _snprintf @@ -217,6 +222,18 @@ static int process_initial_page (format_plugin_t *plugin, ogg_page *page) if (codec) break; #endif + codec = initial_midi_page (plugin, page); + if (codec) + break; + codec = initial_flac_page (plugin, page); + if (codec) + break; +#ifdef HAVE_SPEEX + codec = initial_speex_page (plugin, page); + if (codec) + break; +#endif + /* any others */ ERROR0 ("Seen BOS page with unknown type"); return -1; diff --git a/src/format_speex.c b/src/format_speex.c new file mode 100644 index 00000000..cc89e94a --- /dev/null +++ b/src/format_speex.c @@ -0,0 +1,92 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2000-2004, Jack Moffitt , + * Michael Smith , + * oddsock , + * Karl Heyes + * and others (see AUTHORS for details). + */ + + +/* Ogg codec handler for speex streams */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +typedef struct source_tag source_t; + +#include "format_speex.h" +#include "refbuf.h" +#include "client.h" + +#define CATMODULE "format-speex" +#include "logging.h" + +static void speex_codec_free (ogg_state_t *ogg_info, ogg_codec_t *codec) +{ + ogg_stream_clear (&codec->os); + free (codec); +} + + +static refbuf_t *process_speex_page (ogg_state_t *ogg_info, + ogg_codec_t *codec, ogg_page *page) +{ + refbuf_t *refbuf; + + if (codec->headers < 2) + { + ogg_packet packet; + + ogg_stream_pagein (&codec->os, page); + while (ogg_stream_packetout (&codec->os, &packet) > 0) + { + /* first time around (normal case) yields comments */ + codec->headers++; + } + /* add header page to associated list */ + format_ogg_attach_header (ogg_info, page); + return NULL; + } + refbuf = make_refbuf_with_page (page); + return refbuf; +} + + +ogg_codec_t *initial_speex_page (format_plugin_t *plugin, ogg_page *page) +{ + ogg_state_t *ogg_info = plugin->_state; + ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t)); + ogg_packet packet; + SpeexHeader *header; + + ogg_stream_init (&codec->os, ogg_page_serialno (page)); + ogg_stream_pagein (&codec->os, page); + + ogg_stream_packetout (&codec->os, &packet); + + DEBUG0("checking for speex codec"); + header = speex_packet_to_header (packet.packet, packet.bytes); + if (header == NULL) + { + ogg_stream_clear (&codec->os); + free (header); + free (codec); + return NULL; + } + INFO0 ("seen initial speex header"); + codec->process_page = process_speex_page; + codec->codec_free = speex_codec_free; + codec->headers = 1; + format_ogg_attach_header (ogg_info, page); + free (header); + return codec; +} diff --git a/src/format_speex.h b/src/format_speex.h new file mode 100644 index 00000000..4a3f49f0 --- /dev/null +++ b/src/format_speex.h @@ -0,0 +1,21 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2000-2004, Jack Moffitt , + * oddsock , + * Karl Heyes + * and others (see AUTHORS for details). + */ + + +#ifndef __FORMAT_SPEEX_H +#define __FORMAT_SPEEX_H + +#include "format_ogg.h" + +ogg_codec_t *initial_speex_page (format_plugin_t *plugin, ogg_page *page); + +#endif /* __FORMAT_SPEEX_H */