Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:53 2009

## Asterisk developer's documentation

# format_pcm_alaw.c File Reference

Flat, binary, alaw PCM file format. More...

`#include <unistd.h>`
`#include <netinet/in.h>`
`#include <arpa/inet.h>`
`#include <stdlib.h>`
`#include <sys/time.h>`
`#include <sys/times.h>`
`#include <sys/types.h>`
`#include <stdio.h>`
`#include <errno.h>`
`#include <string.h>`
`#include "asterisk.h"`
`#include "asterisk/lock.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/file.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/sched.h"`
`#include "asterisk/module.h"`
`#include "asterisk/endian.h"`
`#include "asterisk/alaw.h"`

Include dependency graph for format_pcm_alaw.c:

Go to the source code of this file.

## Data Structures

struct | ast_filestream

## Defines

#define | BUF_SIZE 160

## Functions

| AST_MUTEX_DEFINE_STATIC (pcm_lock)
char * | description ()
| Provides a description of the module.
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module ()
| Initialize the module.
static void | pcm_close (struct ast_filestream *s)
static char * | pcm_getcomment (struct ast_filestream *s)
static struct ast_filestream * | pcm_open (FILE *f)
static struct ast_frame * | pcm_read (struct ast_filestream *s, int *whennext)
static struct ast_filestream * | pcm_rewrite (FILE *f, const char *comment)
static int | pcm_seek (struct ast_filestream *fs, long sample_offset, int whence)
static long | pcm_tell (struct ast_filestream *fs)
static int | pcm_trunc (struct ast_filestream *fs)
static int | pcm_write (struct ast_filestream *fs, struct ast_frame *f)
int | unload_module ()
| Cleanup all module structures, sockets, etc.
int | usecount ()
| Provides a usecount.

## Variables

static char | alaw_silence [BUF_SIZE]
static char * | desc = "Raw aLaw 8khz PCM Audio support"
static char * | exts = "alaw|al"
static int | glistcnt = 0
static char * | name = "alaw"

## Detailed Description

Flat, binary, alaw PCM file format.

- File name extensions: alaw, al

Definition in file format_pcm_alaw.c.

## Define Documentation

#define BUF_SIZE 160

Definition at line 50 of file format_pcm_alaw.c.

## Function Documentation

AST_MUTEX_DEFINE_STATIC | ( | pcm_lock |  | ) |

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 343 of file format_pcm_alaw.c.

    00344 {
    00345    return desc;
    00346 }

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 349 of file format_pcm_alaw.c.

References ASTERISK_GPL_KEY.

    00350 {
    00351    return ASTERISK_GPL_KEY;
    00352 }

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 314 of file format_pcm_alaw.c.

References AST_FORMAT_ALAW, ast_format_register(), AST_LIN2A, pcm_close(), pcm_getcomment(), pcm_open(), pcm_read(), pcm_rewrite(), pcm_seek(), pcm_tell(), pcm_trunc(), and pcm_write().

    00315 {
    00316    int index;
    00317
    00318    for (index = 0; index < (sizeof(alaw_silence) / sizeof(alaw_silence[0])); index++)
    00319       alaw_silence[index] = AST_LIN2A(0);
    00320
    00321    return ast_format_register(name, exts, AST_FORMAT_ALAW,
    00322                pcm_open,
    00323                pcm_rewrite,
    00324                pcm_write,
    00325                pcm_seek,
    00326                pcm_trunc,
    00327                pcm_tell,
    00328                pcm_read,
    00329                pcm_close,
    00330                pcm_getcomment);
    00331 }

static void pcm_close | ( | struct ast_filestream * | s | ) | `[static]`

Definition at line 152 of file format_pcm_alaw.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), ast_filestream::f, free, and LOG_WARNING.

    00153 {
    00154    if (ast_mutex_lock(&pcm_lock)) {
    00155       ast_log(LOG_WARNING, "Unable to lock pcm list\n");
    00156       return;
    00157    }
    00158    glistcnt--;
    00159    ast_mutex_unlock(&pcm_lock);
    00160    ast_update_use_count();
    00161    fclose(s->f);
    00162    free(s);
    00163    s = NULL;
    00164 }

static char* pcm_getcomment | ( | struct ast_filestream * | s | ) | `[static]`

Definition at line 309 of file format_pcm_alaw.c.

    00310 {
    00311    return NULL;
    00312 }

static struct ast_filestream* pcm_open | ( | FILE * | f | ) | `[static, read]`

Definition at line 97 of file format_pcm_alaw.c.

References AST_FORMAT_ALAW, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), ast_filestream::buf, ast_frame::data, ast_filestream::f, ast_filestream::fr, ast_frame::frametype, free, LOG_WARNING, malloc, ast_frame::mallocd, ast_frame::src, and ast_frame::subclass.

    00098 {
    00099    /* We don't have any header to read or anything really, but
    00100       if we did, it would go here.  We also might want to check
    00101       and be sure it's a valid file.  */
    00102    struct ast_filestream *tmp;
    00103    if ((tmp = malloc(sizeof(struct ast_filestream)))) {
    00104       memset(tmp, 0, sizeof(struct ast_filestream));
    00105       if (ast_mutex_lock(&pcm_lock)) {
    00106          ast_log(LOG_WARNING, "Unable to lock pcm list\n");
    00107          free(tmp);
    00108          return NULL;
    00109       }
    00110       tmp->f = f;
    00111       tmp->fr.data = tmp->buf;
    00112       tmp->fr.frametype = AST_FRAME_VOICE;
    00113       tmp->fr.subclass = AST_FORMAT_ALAW;
    00114       /* datalen will vary for each frame */
    00115       tmp->fr.src = name;
    00116       tmp->fr.mallocd = 0;
    00117 #ifdef REALTIME_WRITE
    00118       tmp->start_time = get_time();
    00119 #endif
    00120       glistcnt++;
    00121       ast_mutex_unlock(&pcm_lock);
    00122       ast_update_use_count();
    00123    }
    00124    return tmp;
    00125 }

static struct ast_frame* pcm_read | ( | struct ast_filestream * | s,
|  | int * | whennext |
| ) |  |  | `[static, read]`

Definition at line 166 of file format_pcm_alaw.c.

References AST_FORMAT_ALAW, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_filestream::buf, BUF_SIZE, ast_frame::data, ast_frame::datalen, ast_filestream::f, ast_filestream::fr, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, and ast_frame::subclass.

    00167 {
    00168    int res;
    00169    /* Send a frame from the file to the appropriate channel */
    00170
    00171    s->fr.frametype = AST_FRAME_VOICE;
    00172    s->fr.subclass = AST_FORMAT_ALAW;
    00173    s->fr.offset = AST_FRIENDLY_OFFSET;
    00174    s->fr.mallocd = 0;
    00175    s->fr.data = s->buf;
    00176    if ((res = fread(s->buf, 1, BUF_SIZE, s->f)) < 1) {
    00177       if (res)
    00178          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
    00179       return NULL;
    00180    }
    00181    s->fr.samples = res;
    00182    s->fr.datalen = res;
    00183    *whennext = s->fr.samples;
    00184    return &s->fr;
    00185 }

static struct ast_filestream* pcm_rewrite | ( | FILE * | f,
|  | const char * | comment |
| ) |  |  | `[static, read]`

Definition at line 127 of file format_pcm_alaw.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), ast_filestream::f, free, LOG_WARNING, and malloc.

    00128 {
    00129    /* We don't have any header to read or anything really, but
    00130       if we did, it would go here.  We also might want to check
    00131       and be sure it's a valid file.  */
    00132    struct ast_filestream *tmp;
    00133    if ((tmp = malloc(sizeof(struct ast_filestream)))) {
    00134       memset(tmp, 0, sizeof(struct ast_filestream));
    00135       if (ast_mutex_lock(&pcm_lock)) {
    00136          ast_log(LOG_WARNING, "Unable to lock pcm list\n");
    00137          free(tmp);
    00138          return NULL;
    00139       }
    00140       tmp->f = f;
    00141 #ifdef REALTIME_WRITE
    00142       tmp->start_time = get_time();
    00143 #endif
    00144       glistcnt++;
    00145       ast_mutex_unlock(&pcm_lock);
    00146       ast_update_use_count();
    00147    } else
    00148       ast_log(LOG_WARNING, "Out of memory\n");
    00149    return tmp;
    00150 }

static int pcm_seek | ( | struct ast_filestream * | fs,
|  | long | sample_offset,
|  | int | whence |
| ) |  |  | `[static]`

Definition at line 252 of file format_pcm_alaw.c.

References BUF_SIZE, ast_filestream::f, offset, and SEEK_FORCECUR.

    00253 {
    00254    long cur, max, offset = 0;
    00255
    00256    cur = ftell(fs->f);
    00257    fseek(fs->f, 0, SEEK_END);
    00258    max = ftell(fs->f);
    00259
    00260    switch (whence) {
    00261    case SEEK_SET:
    00262       offset = sample_offset;
    00263       break;
    00264    case SEEK_END:
    00265       offset = max - sample_offset;
    00266       break;
    00267    case SEEK_CUR:
    00268    case SEEK_FORCECUR:
    00269       offset = cur + sample_offset;
    00270       break;
    00271    }
    00272
    00273    switch (whence) {
    00274    case SEEK_FORCECUR:
    00275       if (offset > max) {
    00276          size_t left = offset - max;
    00277          size_t res;
    00278
    00279          while (left) {
    00280             res = fwrite(alaw_silence, sizeof(alaw_silence[0]),
    00281                     (left > BUF_SIZE) ? BUF_SIZE : left, fs->f);
    00282             if (res == -1)
    00283                return res;
    00284             left -= res * sizeof(alaw_silence[0]);
    00285          }
    00286          return offset;
    00287       }
    00288       /* fall through */
    00289    default:
    00290       offset = (offset > max) ? max : offset;
    00291       offset = (offset < 0) ? 0 : offset;
    00292       return fseek(fs->f, offset, SEEK_SET);
    00293    }
    00294 }

static long pcm_tell | ( | struct ast_filestream * | fs | ) | `[static]`

Definition at line 301 of file format_pcm_alaw.c.

References ast_filestream::f, and offset.

    00302 {
    00303    off_t offset;
    00304    offset = ftell(fs->f);
    00305    return offset;
    00306 }

static int pcm_trunc | ( | struct ast_filestream * | fs | ) | `[static]`

Definition at line 296 of file format_pcm_alaw.c.

References ast_filestream::f.

    00297 {
    00298    return ftruncate(fileno(fs->f), ftell(fs->f));
    00299 }

static int pcm_write | ( | struct ast_filestream * | fs,
|  | struct ast_frame * | f |
| ) |  |  | `[static]`

Definition at line 187 of file format_pcm_alaw.c.

References AST_FORMAT_ALAW, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_filestream::f, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass.

    00188 {
    00189    int res;
    00190 #ifdef REALTIME_WRITE
    00191    unsigned long cur_time;
    00192    unsigned long fpos;
    00193    struct stat stat_buf;
    00194 #endif
    00195
    00196    if (f->frametype != AST_FRAME_VOICE) {
    00197       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
    00198       return -1;
    00199    }
    00200    if (f->subclass != AST_FORMAT_ALAW) {
    00201       ast_log(LOG_WARNING, "Asked to write non-alaw frame (%d)!\n", f->subclass);
    00202       return -1;
    00203    }
    00204
    00205 #ifdef REALTIME_WRITE
    00206    cur_time = get_time();
    00207    fpos = ( cur_time - fs->start_time ) * 8; /* 8 bytes per msec */
    00208    /* Check if we have written to this position yet. If we have, then increment pos by one frame
    00209    *  for some degree of protection against receiving packets in the same clock tick.
    00210    */
    00211
    00212    fstat(fileno(fs->f), &stat_buf );
    00213    if (stat_buf.st_size > fpos ) {
    00214       fpos += f->datalen;  /* Incrementing with the size of this current frame */
    00215    }
    00216
    00217    if (stat_buf.st_size < fpos) {
    00218       /* fill the gap with 0x55 rather than 0. */
    00219       char buf[ 512 ];
    00220       unsigned long cur, to_write;
    00221
    00222       cur = stat_buf.st_size;
    00223       if (fseek(fs->f, cur, SEEK_SET) < 0) {
    00224          ast_log( LOG_WARNING, "Cannot seek in file: %s\n", strerror(errno) );
    00225          return -1;
    00226       }
    00227       memset(buf, 0x55, 512);
    00228       while (cur < fpos) {
    00229          to_write = fpos - cur;
    00230          if (to_write > 512) {
    00231             to_write = 512;
    00232          }
    00233          fwrite(buf, 1, to_write, fs->f);
    00234          cur += to_write;
    00235       }
    00236    }
    00237
    00238
    00239    if (fseek(s->f, fpos, SEEK_SET) < 0) {
    00240       ast_log( LOG_WARNING, "Cannot seek in file: %s\n", strerror(errno) );
    00241       return -1;
    00242    }
    00243 #endif   /* REALTIME_WRITE */
    00244
    00245    if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
    00246          ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
    00247          return -1;
    00248    }
    00249    return 0;
    00250 }

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 333 of file format_pcm_alaw.c.

References ast_format_unregister().

    00334 {
    00335    return ast_format_unregister(name);
    00336 }

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 338 of file format_pcm_alaw.c.

    00339 {
    00340    return glistcnt;
    00341 }

## Variable Documentation

char alaw_silence[BUF_SIZE]`[static]`

Definition at line 77 of file format_pcm_alaw.c.

char* desc = "Raw aLaw 8khz PCM Audio support"`[static]`

Definition at line 74 of file format_pcm_alaw.c.

char* exts = "alaw|al"`[static]`

Definition at line 75 of file format_pcm_alaw.c.

int glistcnt = 0`[static]`

Definition at line 71 of file format_pcm_alaw.c.

char* name = "alaw"`[static]`

Definition at line 73 of file format_pcm_alaw.c.