Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:06 2009

## 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 226 of file app_ices.c.

    00227 {
    00228    return tdesc;
    00229 }

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

Definition at line 105 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().

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

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    sigset_t fullset, oldset;
    00072
    00073    sigfillset(&fullset);
    00074    pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
    00075
    00076    res = fork();
    00077    if (res < 0)
    00078       ast_log(LOG_WARNING, "Fork failed\n");
    00079    if (res) {
    00080       pthread_sigmask(SIG_SETMASK, &oldset, NULL);
    00081       return res;
    00082    }
    00083
    00084    /* Stop ignoring PIPE */
    00085    signal(SIGPIPE, SIG_DFL);
    00086    pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
    00087
    00088    if (option_highpriority)
    00089       ast_set_priority(0);
    00090    dup2(fd, STDIN_FILENO);
    00091    for (x=STDERR_FILENO + 1;x<1024;x++) {
    00092       if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
    00093          close(x);
    00094    }
    00095    /* Most commonly installed in /usr/local/bin */
    00096    execl(ICES, "ices", filename, (char *)NULL);
    00097    /* But many places has it in /usr/bin */
    00098    execl(LOCAL_ICES, "ices", filename, (char *)NULL);
    00099    /* As a last-ditch effort, try to use PATH */
    00100    execlp("ices", "ices", filename, (char *)NULL);
    00101    ast_log(LOG_WARNING, "Execute of ices failed\n");
    00102    _exit(0);
    00103 }

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 238 of file app_ices.c.

References ASTERISK_GPL_KEY.

    00239 {
    00240    return ASTERISK_GPL_KEY;
    00241 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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.

TE STUFF END

Definition at line 221 of file app_ices.c.

References ast_register_application(), and ices_exec().

    00222 {
    00223    return ast_register_application(app, ices_exec, synopsis, descrip);
    00224 }

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 210 of file app_ices.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

    00211 {
    00212    int res;
    00213
    00214    res = ast_unregister_application(app);
    00215
    00216    STANDARD_HANGUP_LOCALUSERS;
    00217
    00218    return res;
    00219 }

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 231 of file app_ices.c.

References STANDARD_USECOUNT.

    00232 {
    00233    int res;
    00234    STANDARD_USECOUNT(res);
    00235    return res;
    00236 }

## 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.