From d07601c72aefa87b7791ba67220cc6d5c9410604 Mon Sep 17 00:00:00 2001 From: markster Date: Tue, 17 Feb 2004 07:03:14 +0000 Subject: Add Icecast streaming support git-svn-id: http://svn.digium.com/svn/asterisk/trunk@2185 f38db490-d61c-443f-a65b-d21fe96a405b --- CHANGES | 2 + apps/Makefile | 2 +- apps/app_ices.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++ contrib/asterisk-ices.xml | 93 ++++++++++++++++++++++ doc/README.ices | 12 +++ 5 files changed, 305 insertions(+), 1 deletion(-) create mode 100755 apps/app_ices.c create mode 100755 contrib/asterisk-ices.xml create mode 100755 doc/README.ices diff --git a/CHANGES b/CHANGES index d83f7cc42..62bc5d9da 100755 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ + -- Add ices/icecast support + -- Numerous bug fixes Asterisk 0.7.2 -- Countless small bug fixes from bug tracker -- DSP Fixes diff --git a/apps/Makefile b/apps/Makefile index 0fcdd7636..25bd56694 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -25,7 +25,7 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\ app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \ app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \ app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so \ - app_setcdruserfield.so app_random.so + app_setcdruserfield.so app_random.so app_ices.so ifneq (${OSARCH},Darwin) APPS+=app_intercom.so diff --git a/apps/app_ices.c b/apps/app_ices.c new file mode 100755 index 000000000..294ecc604 --- /dev/null +++ b/apps/app_ices.c @@ -0,0 +1,197 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Stream to an icecast server via ICES (see contrib/asterisk-ices.xml) + * + * Copyright (C) 1999, Mark Spencer + * + * Mark Spencer + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../astconf.h" + +#define ICES "/usr/bin/ices" +#define LOCAL_ICES "/usr/local/bin/ices" + +static char *tdesc = "Encode and Stream via icecast and ices"; + +static char *app = "ICES"; + +static char *synopsis = "Encode and stream using 'ices'"; + +static char *descrip = +" ICES(config.xml) Streams to an icecast server using ices\n" +"(available separately). A configuration file must be supplied\n" +"for ices (see examples/asterisk-ices.conf). Returns -1 on\n" +"hangup or 0 otherwise.\n"; + +STANDARD_LOCAL_USER; + +LOCAL_USER_DECL; + +static int icesencode(char *filename, int fd) +{ + int res; + int x; + res = fork(); + if (res < 0) + ast_log(LOG_WARNING, "Fork failed\n"); + if (res) + return res; + dup2(fd, STDIN_FILENO); + for (x=STDERR_FILENO + 1;x<256;x++) { + if ((x != STDIN_FILENO) && (x != STDOUT_FILENO)) + close(x); + } + /* Most commonly installed in /usr/local/bin */ + execl(ICES, "ices", filename, (char *)NULL); + /* But many places has it in /usr/bin */ + execl(LOCAL_ICES, "ices", filename, (char *)NULL); + /* As a last-ditch effort, try to use PATH */ + execlp("ices", "ices", filename, (char *)NULL); + ast_log(LOG_WARNING, "Execute of ices failed\n"); + return -1; +} + +static int ices_exec(struct ast_channel *chan, void *data) +{ + int res=0; + struct localuser *u; + int fds[2]; + int ms = -1; + int pid = -1; + int flags; + int oreadformat; + struct timeval last; + struct ast_frame *f; + char filename[256]=""; + char *c; + last.tv_usec = 0; + last.tv_sec = 0; + if (!data || !strlen(data)) { + ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n"); + return -1; + } + if (pipe(fds)) { + ast_log(LOG_WARNING, "Unable to create pipe\n"); + return -1; + } + flags = fcntl(fds[1], F_GETFL); + fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); + + LOCAL_USER_ADD(u); + ast_stopstream(chan); + + if (chan->_state != AST_STATE_UP) + res = ast_answer(chan); + + if (res) { + close(fds[0]); + close(fds[1]); + ast_log(LOG_WARNING, "Answer failed!\n"); + return -1; + } + + oreadformat = chan->readformat; + res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); + if (res < 0) { + close(fds[0]); + close(fds[1]); + ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); + return -1; + } + if (((char *)data)[0] == '/') + strncpy(filename, (char *)data, sizeof(filename) - 1); + else + snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data); + /* Placeholder for options */ + c = strchr(filename, '|'); + if (c) + *c = '\0'; + res = icesencode(filename, fds[0]); + close(fds[0]); + if (res >= 0) { + pid = res; + for (;;) { + /* Wait for audio, and stream */ + ms = ast_waitfor(chan, -1); + if (ms < 0) { + ast_log(LOG_DEBUG, "Hangup detected\n"); + res = -1; + break; + } + f = ast_read(chan); + if (!f) { + ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); + res = -1; + break; + } + if (f->frametype == AST_FRAME_VOICE) { + res = write(fds[1], f->data, f->datalen); + if (res < 0) { + if (errno != EAGAIN) { + ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); + res = -1; + break; + } + } + } + ast_frfree(f); + } + } + close(fds[1]); + LOCAL_USER_REMOVE(u); + if (pid > -1) + kill(pid, SIGKILL); + if (!res && oreadformat) + ast_set_read_format(chan, oreadformat); + return res; +} + +int unload_module(void) +{ + STANDARD_HANGUP_LOCALUSERS; + return ast_unregister_application(app); +} + +int load_module(void) +{ + return ast_register_application(app, ices_exec, synopsis, descrip); +} + +char *description(void) +{ + return tdesc; +} + +int usecount(void) +{ + int res; + STANDARD_USECOUNT(res); + return res; +} + +char *key() +{ + return ASTERISK_GPL_KEY; +} diff --git a/contrib/asterisk-ices.xml b/contrib/asterisk-ices.xml new file mode 100755 index 000000000..abc028c75 --- /dev/null +++ b/contrib/asterisk-ices.xml @@ -0,0 +1,93 @@ + + + + + 0 + + /var/log/ices + ices.log + + 4 + + 0 + + + + + + + + Example stream name + Example genre + A short description of your stream + http://mysite.org + + + + + stdinpcm + 8000 + 1 + + + 1 + test + + + + + + + + localhost + 8000 + temppass + /example.ogg + 1 + + + + + 0 + 8000 + 1 + + + + 0 + + + + + + + + diff --git a/doc/README.ices b/doc/README.ices new file mode 100755 index 000000000..d75236357 --- /dev/null +++ b/doc/README.ices @@ -0,0 +1,12 @@ +Icecast + Asterisk +================== +The advent of icecast into Asterisk allows you to do neat things like have +a caller stream right into an ice-cast stream as well as using chan_local +to place things like conferences, music on hold, etc. into the stream. + +You'll need to specify a config file for the ices encoder. An example is +included in contrib/asterisk-ices.xml + +Anyway hope you like it. + +Mark -- cgit v1.2.3