aboutsummaryrefslogtreecommitdiffstats
path: root/formats/format_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'formats/format_pcm.c')
-rw-r--r--formats/format_pcm.c76
1 files changed, 51 insertions, 25 deletions
diff --git a/formats/format_pcm.c b/formats/format_pcm.c
index 4adb076cf..80905cdbf 100644
--- a/formats/format_pcm.c
+++ b/formats/format_pcm.c
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 1999 - 2006, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/sched.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
+#include "asterisk/ulaw.h"
#define BUF_SIZE 160 /* 160 samples */
@@ -67,6 +68,8 @@ static char *name = "pcm";
static char *desc = "Raw uLaw 8khz Audio support (PCM)";
static char *exts = "pcm|ulaw|ul|mu";
+static char ulaw_silence[BUF_SIZE];
+
static struct ast_filestream *pcm_open(FILE *f)
{
/* We don't have any header to read or anything really, but
@@ -173,24 +176,44 @@ static int pcm_write(struct ast_filestream *fs, struct ast_frame *f)
static int pcm_seek(struct ast_filestream *fs, long sample_offset, int whence)
{
- off_t offset=0,min,cur,max;
+ long cur, max, offset;
- min = 0;
cur = ftell(fs->f);
- fseek(fs->f, 0, SEEK_END);
- max = ftell(fs->f);
- if (whence == SEEK_SET)
+ max = fseek(fs->f, 0, SEEK_END);
+
+ switch (whence) {
+ case SEEK_SET:
offset = sample_offset;
- else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
- offset = sample_offset + cur;
- else if (whence == SEEK_END)
+ break;
+ case SEEK_END:
offset = max - sample_offset;
- if (whence != SEEK_FORCECUR) {
- offset = (offset > max)?max:offset;
+ break;
+ case SEEK_CUR:
+ case SEEK_FORCECUR:
+ offset = cur + sample_offset;
+ break;
+ }
+
+ switch (whence) {
+ case SEEK_FORCECUR:
+ if (offset > max) {
+ size_t left = offset - max;
+ size_t res;
+
+ while (left) {
+ res = fwrite(ulaw_silence, (left > BUF_SIZE) ? BUF_SIZE : left,
+ sizeof(ulaw_silence[0]), fs->f);
+ if (res == -1)
+ return res;
+ left -= res;
+ }
+ }
+ /* fall through */
+ default:
+ offset = (offset > max) ? max : offset;
+ offset = (offset < 0) ? 0 : offset;
+ return fseek(fs->f, offset, SEEK_SET);
}
- /* always protect against seeking past begining. */
- offset = (offset < min)?min:offset;
- return fseek(fs->f, offset, SEEK_SET);
}
static int pcm_trunc(struct ast_filestream *fs)
@@ -212,18 +235,21 @@ static char *pcm_getcomment(struct ast_filestream *s)
int load_module()
{
+ int index;
+
+ for (index = 0; index < (sizeof(ulaw_silence) / sizeof(ulaw_silence[0])); index++)
+ ulaw_silence[index] = AST_LIN2MU(0);
+
return ast_format_register(name, exts, AST_FORMAT_ULAW,
- pcm_open,
- pcm_rewrite,
- pcm_write,
- pcm_seek,
- pcm_trunc,
- pcm_tell,
- pcm_read,
- pcm_close,
- pcm_getcomment);
-
-
+ pcm_open,
+ pcm_rewrite,
+ pcm_write,
+ pcm_seek,
+ pcm_trunc,
+ pcm_tell,
+ pcm_read,
+ pcm_close,
+ pcm_getcomment);
}
int unload_module()