Thu May 24 14:21:23 2007

Asterisk developer's documentation


app_ices.c File Reference

Stream to an icecast server via ICES (see contrib/asterisk-ices.xml). More...

#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"

Include dependency graph for app_ices.c:

Go to the source code of this file.

Defines

#define ICES   "/usr/bin/ices"
#define LOCAL_ICES   "/usr/local/bin/ices"

Functions

char * description (void)
 Provides a description of the module.
static int ices_exec (struct ast_channel *chan, void *data)
static int icesencode (char *filename, int fd)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

static char * app = "ICES"
static char * descrip
 LOCAL_USER_DECL
 STANDARD_LOCAL_USER
static char * synopsis = "Encode and stream using 'ices'"
static char * tdesc = "Encode and Stream via icecast and ices"


Detailed Description

Stream to an icecast server via ICES (see contrib/asterisk-ices.xml).

Definition in file app_ices.c.


Define Documentation

#define ICES   "/usr/bin/ices"

Definition at line 49 of file app_ices.c.

Referenced by icesencode().

#define LOCAL_ICES   "/usr/local/bin/ices"

Definition at line 50 of file app_ices.c.

Referenced by icesencode().


Function Documentation

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 214 of file app_ices.c.

00215 {
00216    return tdesc;
00217 }

static int ices_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 93 of file app_ices.c.

References ast_channel::_state, ast_answer(), ast_config_AST_CONFIG_DIR, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), AST_STATE_UP, ast_stopstream(), ast_strlen_zero(), ast_waitfor(), ast_frame::data, ast_frame::datalen, localuser::flags, ast_frame::frametype, icesencode(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_WARNING, and ast_channel::readformat.

Referenced by load_module().

00094 {
00095    int res=0;
00096    struct localuser *u;
00097    int fds[2];
00098    int ms = -1;
00099    int pid = -1;
00100    int flags;
00101    int oreadformat;
00102    struct timeval last;
00103    struct ast_frame *f;
00104    char filename[256]="";
00105    char *c;
00106 
00107    if (ast_strlen_zero(data)) {
00108       ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
00109       return -1;
00110    }
00111 
00112    LOCAL_USER_ADD(u);
00113    
00114    last = ast_tv(0, 0);
00115    
00116    if (pipe(fds)) {
00117       ast_log(LOG_WARNING, "Unable to create pipe\n");
00118       LOCAL_USER_REMOVE(u);
00119       return -1;
00120    }
00121    flags = fcntl(fds[1], F_GETFL);
00122    fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
00123    
00124    ast_stopstream(chan);
00125 
00126    if (chan->_state != AST_STATE_UP)
00127       res = ast_answer(chan);
00128       
00129    if (res) {
00130       close(fds[0]);
00131       close(fds[1]);
00132       ast_log(LOG_WARNING, "Answer failed!\n");
00133       LOCAL_USER_REMOVE(u);
00134       return -1;
00135    }
00136 
00137    oreadformat = chan->readformat;
00138    res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00139    if (res < 0) {
00140       close(fds[0]);
00141       close(fds[1]);
00142       ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00143       LOCAL_USER_REMOVE(u);
00144       return -1;
00145    }
00146    if (((char *)data)[0] == '/')
00147       strncpy(filename, (char *)data, sizeof(filename) - 1);
00148    else
00149       snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
00150    /* Placeholder for options */    
00151    c = strchr(filename, '|');
00152    if (c)
00153       *c = '\0';  
00154    res = icesencode(filename, fds[0]);
00155    close(fds[0]);
00156    if (res >= 0) {
00157       pid = res;
00158       for (;;) {
00159          /* Wait for audio, and stream */
00160          ms = ast_waitfor(chan, -1);
00161          if (ms < 0) {
00162             ast_log(LOG_DEBUG, "Hangup detected\n");
00163             res = -1;
00164             break;
00165          }
00166          f = ast_read(chan);
00167          if (!f) {
00168             ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
00169             res = -1;
00170             break;
00171          }
00172          if (f->frametype == AST_FRAME_VOICE) {
00173             res = write(fds[1], f->data, f->datalen);
00174             if (res < 0) {
00175                if (errno != EAGAIN) {
00176                   ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
00177                   res = -1;
00178                   ast_frfree(f);
00179                   break;
00180                }
00181             }
00182          }
00183          ast_frfree(f);
00184       }
00185    }
00186    close(fds[1]);
00187    
00188    if (pid > -1)
00189       kill(pid, SIGKILL);
00190    if (!res && oreadformat)
00191       ast_set_read_format(chan, oreadformat);
00192 
00193    LOCAL_USER_REMOVE(u);
00194 
00195    return res;
00196 }

static int icesencode ( char *  filename,
int  fd 
) [static]

Definition at line 67 of file app_ices.c.

References ast_log(), ast_set_priority(), ICES, LOCAL_ICES, LOG_WARNING, and option_highpriority.

Referenced by ices_exec().

00068 {
00069    int res;
00070    int x;
00071    res = fork();
00072    if (res < 0) 
00073       ast_log(LOG_WARNING, "Fork failed\n");
00074    if (res)
00075       return res;
00076    if (option_highpriority)
00077       ast_set_priority(0);
00078    dup2(fd, STDIN_FILENO);
00079    for (x=STDERR_FILENO + 1;x<256;x++) {
00080       if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
00081          close(x);
00082    }
00083    /* Most commonly installed in /usr/local/bin */
00084    execl(ICES, "ices", filename, (char *)NULL);
00085    /* But many places has it in /usr/bin */
00086    execl(LOCAL_ICES, "ices", filename, (char *)NULL);
00087    /* As a last-ditch effort, try to use PATH */
00088    execlp("ices", "ices", filename, (char *)NULL);
00089    ast_log(LOG_WARNING, "Execute of ices failed\n");
00090    return -1;
00091 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 226 of file app_ices.c.

References ASTERISK_GPL_KEY.

00227 {
00228    return ASTERISK_GPL_KEY;
00229 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 209 of file app_ices.c.

References ast_register_application(), and ices_exec().

00210 {
00211    return ast_register_application(app, ices_exec, synopsis, descrip);
00212 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 198 of file app_ices.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00199 {
00200    int res;
00201 
00202    res = ast_unregister_application(app);
00203 
00204    STANDARD_HANGUP_LOCALUSERS;
00205 
00206    return res;
00207 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 219 of file app_ices.c.

References STANDARD_USECOUNT.

00220 {
00221    int res;
00222    STANDARD_USECOUNT(res);
00223    return res;
00224 }


Variable Documentation

char* app = "ICES" [static]

Definition at line 54 of file app_ices.c.

char* descrip [static]

Initial value:

 
"  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). \n"

Definition at line 58 of file app_ices.c.

LOCAL_USER_DECL

Definition at line 65 of file app_ices.c.

STANDARD_LOCAL_USER

Definition at line 63 of file app_ices.c.

char* synopsis = "Encode and stream using 'ices'" [static]

Definition at line 56 of file app_ices.c.

char* tdesc = "Encode and Stream via icecast and ices" [static]

Definition at line 52 of file app_ices.c.


Generated on Thu May 24 14:21:24 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.7