Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:52 2009

## Asterisk developer's documentation

# format_gsm.c File Reference

Save to raw, headerless GSM data. More...

`#include <unistd.h>`
`#include <netinet/in.h>`
`#include <arpa/inet.h>`
`#include <stdlib.h>`
`#include <sys/time.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 "msgsm.h"`

Include dependency graph for format_gsm.c:

Go to the source code of this file.

## Data Structures

struct | ast_filestream

## Functions

| AST_MUTEX_DEFINE_STATIC (gsm_lock)
char * | description ()
| Provides a description of the module.
static void | gsm_close (struct ast_filestream *s)
static char * | gsm_getcomment (struct ast_filestream *s)
static struct ast_filestream * | gsm_open (FILE *f)
static struct ast_frame * | gsm_read (struct ast_filestream *s, int *whennext)
static struct ast_filestream * | gsm_rewrite (FILE *f, const char *comment)
static int | gsm_seek (struct ast_filestream *fs, long sample_offset, int whence)
static long | gsm_tell (struct ast_filestream *fs)
static int | gsm_trunc (struct ast_filestream *fs)
static int | gsm_write (struct ast_filestream *fs, struct ast_frame *f)
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module ()
| Initialize the module.
int | unload_module ()
| Cleanup all module structures, sockets, etc.
int | usecount ()
| Provides a usecount.

## Variables

static char * | desc = "Raw GSM data"
static char * | exts = "gsm"
static int | glistcnt = 0
char | gsm_silence []
static char * | name = "gsm"

## Detailed Description

Save to raw, headerless GSM data.

- File name extension: gsm

Definition in file format_gsm.c.

## Function Documentation

AST_MUTEX_DEFINE_STATIC | ( | gsm_lock |  | ) |

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 271 of file format_gsm.c.

    00272 {
    00273    return desc;
    00274 }

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

Definition at line 130 of file format_gsm.c.

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

Referenced by load_module().

    00131 {
    00132    if (ast_mutex_lock(&gsm_lock)) {
    00133       ast_log(LOG_WARNING, "Unable to lock gsm list\n");
    00134       return;
    00135    }
    00136    glistcnt--;
    00137    ast_mutex_unlock(&gsm_lock);
    00138    ast_update_use_count();
    00139    fclose(s->f);
    00140    free(s);
    00141 }

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

Definition at line 240 of file format_gsm.c.

Referenced by load_module().

    00241 {
    00242    return NULL;
    00243 }

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

Definition at line 81 of file format_gsm.c.

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

Referenced by load_module().

    00082 {
    00083    /* We don't have any header to read or anything really, but
    00084       if we did, it would go here.  We also might want to check
    00085       and be sure it's a valid file.  */
    00086    struct ast_filestream *tmp;
    00087    if ((tmp = malloc(sizeof(struct ast_filestream)))) {
    00088       memset(tmp, 0, sizeof(struct ast_filestream));
    00089       if (ast_mutex_lock(&gsm_lock)) {
    00090          ast_log(LOG_WARNING, "Unable to lock gsm list\n");
    00091          free(tmp);
    00092          return NULL;
    00093       }
    00094       tmp->f = f;
    00095       tmp->fr.data = tmp->gsm;
    00096       tmp->fr.frametype = AST_FRAME_VOICE;
    00097       tmp->fr.subclass = AST_FORMAT_GSM;
    00098       /* datalen will vary for each frame */
    00099       tmp->fr.src = name;
    00100       tmp->fr.mallocd = 0;
    00101       glistcnt++;
    00102       ast_mutex_unlock(&gsm_lock);
    00103       ast_update_use_count();
    00104    }
    00105    return tmp;
    00106 }

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

Definition at line 143 of file format_gsm.c.

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

Referenced by load_module().

    00144 {
    00145    int res;
    00146    s->fr.frametype = AST_FRAME_VOICE;
    00147    s->fr.subclass = AST_FORMAT_GSM;
    00148    s->fr.offset = AST_FRIENDLY_OFFSET;
    00149    s->fr.samples = 160;
    00150    s->fr.datalen = 33;
    00151    s->fr.mallocd = 0;
    00152    s->fr.data = s->gsm;
    00153    if ((res = fread(s->gsm, 1, 33, s->f)) != 33) {
    00154       if (res)
    00155          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
    00156       return NULL;
    00157    }
    00158    *whennext = 160;
    00159    return &s->fr;
    00160 }

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

Definition at line 108 of file format_gsm.c.

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

Referenced by load_module().

    00109 {
    00110    /* We don't have any header to read or anything really, but
    00111       if we did, it would go here.  We also might want to check
    00112       and be sure it's a valid file.  */
    00113    struct ast_filestream *tmp;
    00114    if ((tmp = malloc(sizeof(struct ast_filestream)))) {
    00115       memset(tmp, 0, sizeof(struct ast_filestream));
    00116       if (ast_mutex_lock(&gsm_lock)) {
    00117          ast_log(LOG_WARNING, "Unable to lock gsm list\n");
    00118          free(tmp);
    00119          return NULL;
    00120       }
    00121       tmp->f = f;
    00122       glistcnt++;
    00123       ast_mutex_unlock(&gsm_lock);
    00124       ast_update_use_count();
    00125    } else
    00126       ast_log(LOG_WARNING, "Out of memory\n");
    00127    return tmp;
    00128 }

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

Definition at line 198 of file format_gsm.c.

References ast_filestream::f, offset, and SEEK_FORCECUR.

Referenced by load_module().

    00199 {
    00200    off_t offset=0,min,cur,max,distance;
    00201
    00202    min = 0;
    00203    cur = ftell(fs->f);
    00204    fseek(fs->f, 0, SEEK_END);
    00205    max = ftell(fs->f);
    00206    /* have to fudge to frame here, so not fully to sample */
    00207    distance = (sample_offset/160) * 33;
    00208    if(whence == SEEK_SET)
    00209       offset = distance;
    00210    else if(whence == SEEK_CUR || whence == SEEK_FORCECUR)
    00211       offset = distance + cur;
    00212    else if(whence == SEEK_END)
    00213       offset = max - distance;
    00214    /* Always protect against seeking past the begining. */
    00215    offset = (offset < min)?min:offset;
    00216    if (whence != SEEK_FORCECUR) {
    00217       offset = (offset > max)?max:offset;
    00218    } else if (offset > max) {
    00219       int i;
    00220       fseek(fs->f, 0, SEEK_END);
    00221       for (i=0; i< (offset - max) / 33; i++) {
    00222          fwrite(gsm_silence, 1, 33, fs->f);
    00223       }
    00224    }
    00225    return fseek(fs->f, offset, SEEK_SET);
    00226 }

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

Definition at line 233 of file format_gsm.c.

References ast_filestream::f, and offset.

Referenced by load_module().

    00234 {
    00235    off_t offset;
    00236    offset = ftell(fs->f);
    00237    return (offset/33)*160;
    00238 }

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

Definition at line 228 of file format_gsm.c.

References ast_filestream::f.

Referenced by load_module().

    00229 {
    00230    return ftruncate(fileno(fs->f), ftell(fs->f));
    00231 }

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

Definition at line 162 of file format_gsm.c.

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

Referenced by load_module().

    00163 {
    00164    int res;
    00165    unsigned char gsm[66];
    00166    if (f->frametype != AST_FRAME_VOICE) {
    00167       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
    00168       return -1;
    00169    }
    00170    if (f->subclass != AST_FORMAT_GSM) {
    00171       ast_log(LOG_WARNING, "Asked to write non-GSM frame (%d)!\n", f->subclass);
    00172       return -1;
    00173    }
    00174    if (!(f->datalen % 65)) {
    00175       /* This is in MSGSM format, need to be converted */
    00176       int len=0;
    00177       while(len < f->datalen) {
    00178          conv65(f->data + len, gsm);
    00179          if ((res = fwrite(gsm, 1, 66, fs->f)) != 66) {
    00180             ast_log(LOG_WARNING, "Bad write (%d/66): %s\n", res, strerror(errno));
    00181             return -1;
    00182          }
    00183          len += 65;
    00184       }
    00185    } else {
    00186       if (f->datalen % 33) {
    00187          ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 33\n", f->datalen);
    00188          return -1;
    00189       }
    00190       if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
    00191             ast_log(LOG_WARNING, "Bad write (%d/33): %s\n", res, strerror(errno));
    00192             return -1;
    00193       }
    00194    }
    00195    return 0;
    00196 }

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 277 of file format_gsm.c.

References ASTERISK_GPL_KEY.

    00278 {
    00279    return ASTERISK_GPL_KEY;
    00280 }

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 245 of file format_gsm.c.

References AST_FORMAT_GSM, ast_format_register(), gsm_close(), gsm_getcomment(), gsm_open(), gsm_read(), gsm_rewrite(), gsm_seek(), gsm_tell(), gsm_trunc(), and gsm_write().

    00246 {
    00247    return ast_format_register(name, exts, AST_FORMAT_GSM,
    00248                         gsm_open,
    00249                         gsm_rewrite,
    00250                         gsm_write,
    00251                         gsm_seek,
    00252                         gsm_trunc,
    00253                         gsm_tell,
    00254                         gsm_read,
    00255                         gsm_close,
    00256                         gsm_getcomment);
    00257
    00258
    00259 }

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 261 of file format_gsm.c.

References ast_format_unregister().

    00262 {
    00263    return ast_format_unregister(name);
    00264 }

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 266 of file format_gsm.c.

    00267 {
    00268    return glistcnt;
    00269 }

## Variable Documentation

char* desc = "Raw GSM data"`[static]`

Definition at line 78 of file format_gsm.c.

char* exts = "gsm"`[static]`

Definition at line 79 of file format_gsm.c.

int glistcnt = 0`[static]`

Definition at line 75 of file format_gsm.c.

char gsm_silence[]

Initial value:

    {0xD8,0x20,0xA2,0xE1,0x5A,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49
    ,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24
    ,0x92,0x49,0x24}

Definition at line 55 of file format_gsm.c.

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

Definition at line 77 of file format_gsm.c.