#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <soundcard.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/endian.h"
#include "busy.h"
#include "ringtone.h"
#include "ring10.h"
#include "answer.h"
Go to the source code of this file.
Data Structures | |
struct | chan_oss_pvt |
struct | sound |
Defines | |
#define | BUFFER_FMT ((buffersize * 10) << 16) | (0x0006); |
#define | DEV_DSP "/dev/dsp" |
#define | FRAME_SIZE 160 |
#define | MAX_BUFFER_SIZE 100 |
#define | MIN(a, b) ((a) < (b) ? (a) : (b)) |
#define | MIN_SWITCH_TIME 600 |
Functions | |
static void | answer_sound (void) |
AST_MUTEX_DEFINE_STATIC (usecnt_lock) | |
static char * | autoanswer_complete (char *line, char *word, int pos, int state) |
static int | console_answer (int fd, int argc, char *argv[]) |
static int | console_autoanswer (int fd, int argc, char *argv[]) |
static int | console_dial (int fd, int argc, char *argv[]) |
static int | console_flash (int fd, int argc, char *argv[]) |
static int | console_hangup (int fd, int argc, char *argv[]) |
static int | console_sendtext (int fd, int argc, char *argv[]) |
static int | console_transfer (int fd, int argc, char *argv[]) |
char * | description () |
Provides a description of the module. | |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module () |
Initialize the module. | |
static int | oss_answer (struct ast_channel *c) |
static int | oss_call (struct ast_channel *c, char *dest, int timeout) |
static int | oss_digit (struct ast_channel *c, char digit) |
static int | oss_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | oss_hangup (struct ast_channel *c) |
static int | oss_indicate (struct ast_channel *chan, int cond) |
static struct ast_channel * | oss_new (struct chan_oss_pvt *p, int state) |
static struct ast_frame * | oss_read (struct ast_channel *chan) |
static struct ast_channel * | oss_request (const char *type, int format, void *data, int *cause) |
static int | oss_text (struct ast_channel *c, const char *text) |
static int | oss_write (struct ast_channel *chan, struct ast_frame *f) |
static int | send_sound (void) |
static int | setformat (void) |
static void * | sound_thread (void *unused) |
static int | soundcard_init (void) |
static int | soundcard_setinput (int force) |
static int | soundcard_setoutput (int force) |
static int | soundcard_writeframe (short *data) |
static int | time_has_passed (void) |
int | unload_module () |
Cleanup all module structures, sockets, etc. | |
int | usecount () |
Provides a usecount. | |
Variables | |
static char | answer_usage [] |
static int | autoanswer = 1 |
static char | autoanswer_usage [] |
static int | buffersize = 3 |
static const char | config [] = "oss.conf" |
static char | context [AST_MAX_CONTEXT] = "default" |
static int | cursound = -1 |
static const char | desc [] = "OSS Console Channel Driver" |
static char | dial_usage [] |
static char | exten [AST_MAX_EXTENSION] = "s" |
static char | flash_usage [] |
static int | full_duplex = 0 |
static char | hangup_usage [] |
static int | hookstate = 0 |
static char | language [MAX_LANGUAGE] = "" |
static struct timeval | lasttime |
static struct ast_cli_entry | myclis [] |
static int | nosound = 0 |
static int | offset = 0 |
static struct chan_oss_pvt | oss |
static const struct ast_channel_tech | oss_tech |
static int | playbackonly = 0 |
static int | readmode = 1 |
static int | sampsent = 0 |
static char | sendtext_usage [] |
static short | silence [FRAME_SIZE] = {0, } |
static int | silencelen = 0 |
static int | silencesuppression = 0 |
static int | silencethreshold = 1000 |
static int | sndcmd [2] |
static int | sounddev = -1 |
static struct sound | sounds [] |
static pthread_t | sthread |
static const char | tdesc [] = "OSS Console Channel Driver" |
static char | transfer_usage [] |
static const char | type [] = "Console" |
static int | usecnt |
|
Definition at line 81 of file chan_oss_old.c. |
|
Definition at line 72 of file chan_oss_old.c. |
|
Definition at line 76 of file chan_oss_old.c. |
|
Definition at line 182 of file chan_oss_old.c. |
|
|
|
Definition at line 84 of file chan_oss_old.c. |
|
Definition at line 531 of file chan_oss_old.c. References nosound, and sndcmd. 00532 { 00533 int res; 00534 nosound = 1; 00535 res = 4; 00536 write(sndcmd[1], &res, sizeof(res)); 00537 00538 }
|
|
|
|
Definition at line 837 of file chan_oss_old.c. References ast_strlen_zero(), MIN, and strdup. 00838 { 00839 #ifndef MIN 00840 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 00841 #endif 00842 switch(state) { 00843 case 0: 00844 if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2))) 00845 return strdup("on"); 00846 case 1: 00847 if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3))) 00848 return strdup("off"); 00849 default: 00850 return NULL; 00851 } 00852 return NULL; 00853 }
|
|
Definition at line 861 of file chan_oss_old.c. References answer_sound(), ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), cursound, oss, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 00862 { 00863 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00864 if (argc != 1) 00865 return RESULT_SHOWUSAGE; 00866 if (!oss.owner) { 00867 ast_cli(fd, "No one is calling us\n"); 00868 return RESULT_FAILURE; 00869 } 00870 hookstate = 1; 00871 cursound = -1; 00872 ast_queue_frame(oss.owner, &f); 00873 answer_sound(); 00874 return RESULT_SUCCESS; 00875 }
|
|
Definition at line 819 of file chan_oss_old.c. References ast_cli(), autoanswer, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 00820 { 00821 if ((argc != 1) && (argc != 2)) 00822 return RESULT_SHOWUSAGE; 00823 if (argc == 1) { 00824 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off"); 00825 return RESULT_SUCCESS; 00826 } else { 00827 if (!strcasecmp(argv[1], "on")) 00828 autoanswer = -1; 00829 else if (!strcasecmp(argv[1], "off")) 00830 autoanswer = 0; 00831 else 00832 return RESULT_SHOWUSAGE; 00833 } 00834 return RESULT_SUCCESS; 00835 }
|
|
Definition at line 955 of file chan_oss_old.c. References ast_cli(), AST_FRAME_DTMF, ast_queue_frame(), oss, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_frame::subclass. 00956 { 00957 char tmp[256], *tmp2; 00958 char *mye, *myc; 00959 int x; 00960 struct ast_frame f = { AST_FRAME_DTMF, 0 }; 00961 if ((argc != 1) && (argc != 2)) 00962 return RESULT_SHOWUSAGE; 00963 if (oss.owner) { 00964 if (argc == 2) { 00965 for (x=0;x<strlen(argv[1]);x++) { 00966 f.subclass = argv[1][x]; 00967 ast_queue_frame(oss.owner, &f); 00968 } 00969 } else { 00970 ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n"); 00971 return RESULT_FAILURE; 00972 } 00973 return RESULT_SUCCESS; 00974 } 00975 mye = exten; 00976 myc = context; 00977 if (argc == 2) { 00978 char *stringp=NULL; 00979 strncpy(tmp, argv[1], sizeof(tmp)-1); 00980 stringp=tmp; 00981 strsep(&stringp, "@"); 00982 tmp2 = strsep(&stringp, "@"); 00983 if (!ast_strlen_zero(tmp)) 00984 mye = tmp; 00985 if (!ast_strlen_zero(tmp2)) 00986 myc = tmp2; 00987 } 00988 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 00989 strncpy(oss.exten, mye, sizeof(oss.exten)-1); 00990 strncpy(oss.context, myc, sizeof(oss.context)-1); 00991 hookstate = 1; 00992 oss_new(&oss, AST_STATE_RINGING); 00993 } else 00994 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc); 00995 return RESULT_SUCCESS; 00996 }
|
|
Definition at line 929 of file chan_oss_old.c. References ast_cli(), AST_CONTROL_FLASH, AST_FRAME_CONTROL, ast_queue_frame(), cursound, oss, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 00930 { 00931 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH }; 00932 if (argc != 1) 00933 return RESULT_SHOWUSAGE; 00934 cursound = -1; 00935 if (!oss.owner) { 00936 ast_cli(fd, "No call to flash\n"); 00937 return RESULT_FAILURE; 00938 } 00939 hookstate = 0; 00940 if (oss.owner) { 00941 ast_queue_frame(oss.owner, &f); 00942 } 00943 return RESULT_SUCCESS; 00944 }
|
|
Definition at line 913 of file chan_oss_old.c. References ast_cli(), ast_queue_hangup(), cursound, oss, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 00914 { 00915 if (argc != 1) 00916 return RESULT_SHOWUSAGE; 00917 cursound = -1; 00918 if (!oss.owner && !hookstate) { 00919 ast_cli(fd, "No call to hangup up\n"); 00920 return RESULT_FAILURE; 00921 } 00922 hookstate = 0; 00923 if (oss.owner) { 00924 ast_queue_hangup(oss.owner); 00925 } 00926 return RESULT_SUCCESS; 00927 }
|
|
Definition at line 881 of file chan_oss_old.c. References ast_cli(), AST_FRAME_TEXT, ast_queue_frame(), ast_strlen_zero(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, oss, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_frame::subclass. 00882 { 00883 int tmparg = 2; 00884 char text2send[256] = ""; 00885 struct ast_frame f = { 0, }; 00886 if (argc < 2) 00887 return RESULT_SHOWUSAGE; 00888 if (!oss.owner) { 00889 ast_cli(fd, "No one is calling us\n"); 00890 return RESULT_FAILURE; 00891 } 00892 if (!ast_strlen_zero(text2send)) 00893 ast_cli(fd, "Warning: message already waiting to be sent, overwriting\n"); 00894 text2send[0] = '\0'; 00895 while(tmparg < argc) { 00896 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1); 00897 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1); 00898 } 00899 if (!ast_strlen_zero(text2send)) { 00900 f.frametype = AST_FRAME_TEXT; 00901 f.subclass = 0; 00902 f.data = text2send; 00903 f.datalen = strlen(text2send); 00904 ast_queue_frame(oss.owner, &f); 00905 } 00906 return RESULT_SUCCESS; 00907 }
|
|
Definition at line 1002 of file chan_oss_old.c. References ast_async_goto(), ast_bridged_channel(), ast_cli(), ast_exists_extension(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::name, oss, chan_oss_pvt::owner, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 01003 { 01004 char tmp[256]; 01005 char *context; 01006 if (argc != 2) 01007 return RESULT_SHOWUSAGE; 01008 if (oss.owner && ast_bridged_channel(oss.owner)) { 01009 strncpy(tmp, argv[1], sizeof(tmp) - 1); 01010 context = strchr(tmp, '@'); 01011 if (context) { 01012 *context = '\0'; 01013 context++; 01014 } else 01015 context = oss.owner->context; 01016 if (ast_exists_extension(ast_bridged_channel(oss.owner), context, tmp, 1, ast_bridged_channel(oss.owner)->cid.cid_num)) { 01017 ast_cli(fd, "Whee, transferring %s to %s@%s.\n", 01018 ast_bridged_channel(oss.owner)->name, tmp, context); 01019 if (ast_async_goto(ast_bridged_channel(oss.owner), context, tmp, 1)) 01020 ast_cli(fd, "Failed to transfer :(\n"); 01021 } else { 01022 ast_cli(fd, "No such extension exists\n"); 01023 } 01024 } else { 01025 ast_cli(fd, "There is no call to transfer\n"); 01026 } 01027 return RESULT_SUCCESS; 01028 }
|
|
Provides a description of the module.
Definition at line 1119 of file chan_oss_old.c. 01120 { 01121 return (char *) desc; 01122 }
|
|
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; }
Definition at line 1129 of file chan_oss_old.c. References ASTERISK_GPL_KEY. 01130 { 01131 return ASTERISK_GPL_KEY; 01132 }
|
|
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.
Definition at line 1045 of file chan_oss_old.c. References ast_channel_register(), ast_cli_register(), ast_config_load(), ast_log(), ast_true(), ast_variable_browse(), ast_verbose(), autoanswer, cfg, full_duplex, LOG_ERROR, LOG_WARNING, myclis, ast_variable::name, ast_variable::next, option_verbose, oss_tech, sndcmd, soundcard_init(), ast_variable::value, and VERBOSE_PREFIX_2. 01046 { 01047 int res; 01048 int x; 01049 struct ast_config *cfg; 01050 struct ast_variable *v; 01051 res = pipe(sndcmd); 01052 if (res) { 01053 ast_log(LOG_ERROR, "Unable to create pipe\n"); 01054 return -1; 01055 } 01056 res = soundcard_init(); 01057 if (res < 0) { 01058 if (option_verbose > 1) { 01059 ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n"); 01060 ast_verbose(VERBOSE_PREFIX_2 "Turn off OSS support by adding 'noload=chan_oss.so' in /etc/asterisk/modules.conf\n"); 01061 } 01062 return 0; 01063 } 01064 if (!full_duplex) 01065 ast_log(LOG_WARNING, "XXX I don't work right with non-full duplex sound cards XXX\n"); 01066 res = ast_channel_register(&oss_tech); 01067 if (res < 0) { 01068 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", type); 01069 return -1; 01070 } 01071 for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++) 01072 ast_cli_register(myclis + x); 01073 if ((cfg = ast_config_load(config))) { 01074 v = ast_variable_browse(cfg, "general"); 01075 while(v) { 01076 if (!strcasecmp(v->name, "autoanswer")) 01077 autoanswer = ast_true(v->value); 01078 else if (!strcasecmp(v->name, "silencesuppression")) 01079 silencesuppression = ast_true(v->value); 01080 else if (!strcasecmp(v->name, "silencethreshold")) 01081 silencethreshold = atoi(v->value); 01082 else if (!strcasecmp(v->name, "context")) 01083 strncpy(context, v->value, sizeof(context)-1); 01084 else if (!strcasecmp(v->name, "language")) 01085 strncpy(language, v->value, sizeof(language)-1); 01086 else if (!strcasecmp(v->name, "extension")) 01087 strncpy(exten, v->value, sizeof(exten)-1); 01088 else if (!strcasecmp(v->name, "playbackonly")) 01089 playbackonly = ast_true(v->value); 01090 v=v->next; 01091 } 01092 ast_config_destroy(cfg); 01093 } 01094 ast_pthread_create(&sthread, NULL, sound_thread, NULL); 01095 return 0; 01096 }
|
|
Definition at line 540 of file chan_oss_old.c. References answer_sound(), ast_setstate(), AST_STATE_UP, ast_verbose(), cursound, and nosound. 00541 { 00542 ast_verbose( " << Console call has been answered >> \n"); 00543 answer_sound(); 00544 ast_setstate(c, AST_STATE_UP); 00545 cursound = -1; 00546 nosound=0; 00547 return 0; 00548 }
|
|
Definition at line 510 of file chan_oss_old.c. References AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_queue_frame(), ast_verbose(), autoanswer, ast_frame::frametype, nosound, sndcmd, and ast_frame::subclass. 00511 { 00512 int res = 3; 00513 struct ast_frame f = { 0, }; 00514 ast_verbose( " << Call placed to '%s' on console >> \n", dest); 00515 if (autoanswer) { 00516 ast_verbose( " << Auto-answered >> \n" ); 00517 f.frametype = AST_FRAME_CONTROL; 00518 f.subclass = AST_CONTROL_ANSWER; 00519 ast_queue_frame(c, &f); 00520 } else { 00521 nosound = 1; 00522 ast_verbose( " << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00523 f.frametype = AST_FRAME_CONTROL; 00524 f.subclass = AST_CONTROL_RINGING; 00525 ast_queue_frame(c, &f); 00526 write(sndcmd[1], &res, sizeof(res)); 00527 } 00528 return 0; 00529 }
|
|
Definition at line 498 of file chan_oss_old.c. References ast_verbose(). 00499 { 00500 ast_verbose( " << Console Received digit %c >> \n", digit); 00501 return 0; 00502 }
|
|
Definition at line 729 of file chan_oss_old.c. References chan_oss_pvt::owner, and ast_channel::tech_pvt. 00730 { 00731 struct chan_oss_pvt *p = newchan->tech_pvt; 00732 p->owner = newchan; 00733 return 0; 00734 }
|
|
Definition at line 550 of file chan_oss_old.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), autoanswer, cursound, oss, chan_oss_pvt::owner, sndcmd, ast_channel::tech_pvt, and usecnt_lock. 00551 { 00552 int res = 0; 00553 cursound = -1; 00554 c->tech_pvt = NULL; 00555 oss.owner = NULL; 00556 ast_verbose( " << Hangup on console >> \n"); 00557 ast_mutex_lock(&usecnt_lock); 00558 usecnt--; 00559 ast_mutex_unlock(&usecnt_lock); 00560 if (hookstate) { 00561 if (autoanswer) { 00562 /* Assume auto-hangup too */ 00563 hookstate = 0; 00564 } else { 00565 /* Make congestion noise */ 00566 res = 2; 00567 write(sndcmd[1], &res, sizeof(res)); 00568 hookstate = 0; 00569 } 00570 } 00571 return 0; 00572 }
|
|
Definition at line 736 of file chan_oss_old.c. References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_RINGING, ast_log(), cursound, LOG_WARNING, ast_channel::name, and sndcmd. 00737 { 00738 int res; 00739 switch(cond) { 00740 case AST_CONTROL_BUSY: 00741 res = 1; 00742 break; 00743 case AST_CONTROL_CONGESTION: 00744 res = 2; 00745 break; 00746 case AST_CONTROL_RINGING: 00747 res = 0; 00748 break; 00749 case -1: 00750 cursound = -1; 00751 return 0; 00752 default: 00753 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name); 00754 return -1; 00755 } 00756 if (res > -1) { 00757 write(sndcmd[1], &res, sizeof(res)); 00758 } 00759 return 0; 00760 }
|
|
|
Definition at line 660 of file chan_oss_old.c. References ast_channel::_state, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), AST_STATE_UP, CRASH, ast_frame::data, ast_frame::datalen, ast_frame::delivery, FRAME_SIZE, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, soundcard_setinput(), sounddev, ast_frame::src, and ast_frame::subclass. 00661 { 00662 static struct ast_frame f; 00663 static char buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET]; 00664 static int readpos = 0; 00665 int res; 00666 00667 #if 0 00668 ast_log(LOG_DEBUG, "oss_read()\n"); 00669 #endif 00670 00671 f.frametype = AST_FRAME_NULL; 00672 f.subclass = 0; 00673 f.samples = 0; 00674 f.datalen = 0; 00675 f.data = NULL; 00676 f.offset = 0; 00677 f.src = type; 00678 f.mallocd = 0; 00679 f.delivery.tv_sec = 0; 00680 f.delivery.tv_usec = 0; 00681 00682 res = soundcard_setinput(0); 00683 if (res < 0) { 00684 ast_log(LOG_WARNING, "Unable to set input mode\n"); 00685 return NULL; 00686 } 00687 if (res > 0) { 00688 /* Theoretically shouldn't happen, but anyway, return a NULL frame */ 00689 return &f; 00690 } 00691 res = read(sounddev, buf + AST_FRIENDLY_OFFSET + readpos, FRAME_SIZE * 2 - readpos); 00692 if (res < 0) { 00693 ast_log(LOG_WARNING, "Error reading from sound device (If you're running 'artsd' then kill it): %s\n", strerror(errno)); 00694 #if 0 00695 CRASH; 00696 #endif 00697 return NULL; 00698 } 00699 readpos += res; 00700 00701 if (readpos >= FRAME_SIZE * 2) { 00702 /* A real frame */ 00703 readpos = 0; 00704 if (chan->_state != AST_STATE_UP) { 00705 /* Don't transmit unless it's up */ 00706 return &f; 00707 } 00708 f.frametype = AST_FRAME_VOICE; 00709 f.subclass = AST_FORMAT_SLINEAR; 00710 f.samples = FRAME_SIZE; 00711 f.datalen = FRAME_SIZE * 2; 00712 f.data = buf + AST_FRIENDLY_OFFSET; 00713 f.offset = AST_FRIENDLY_OFFSET; 00714 f.src = type; 00715 f.mallocd = 0; 00716 f.delivery.tv_sec = 0; 00717 f.delivery.tv_usec = 0; 00718 #if 0 00719 { static int fd = -1; 00720 if (fd < 0) 00721 fd = open("output.raw", O_RDWR | O_TRUNC | O_CREAT); 00722 write(fd, f.data, f.datalen); 00723 } 00724 #endif 00725 } 00726 return &f; 00727 }
|
|
Definition at line 798 of file chan_oss_old.c. References AST_CAUSE_BUSY, AST_FORMAT_SLINEAR, ast_log(), AST_STATE_DOWN, LOG_NOTICE, LOG_WARNING, oss, oss_new(), and chan_oss_pvt::owner. 00799 { 00800 int oldformat = format; 00801 struct ast_channel *tmp; 00802 format &= AST_FORMAT_SLINEAR; 00803 if (!format) { 00804 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat); 00805 return NULL; 00806 } 00807 if (oss.owner) { 00808 ast_log(LOG_NOTICE, "Already have a call on the OSS channel\n"); 00809 *cause = AST_CAUSE_BUSY; 00810 return NULL; 00811 } 00812 tmp= oss_new(&oss, AST_STATE_DOWN); 00813 if (!tmp) { 00814 ast_log(LOG_WARNING, "Unable to create new OSS channel\n"); 00815 } 00816 return tmp; 00817 }
|
|
Definition at line 504 of file chan_oss_old.c. References ast_verbose(). 00505 { 00506 ast_verbose( " << Console Received text %s >> \n", text); 00507 return 0; 00508 }
|
|
Definition at line 609 of file chan_oss_old.c. References ast_log(), cursound, ast_frame::data, ast_frame::datalen, FRAME_SIZE, full_duplex, LOG_WARNING, nosound, soundcard_setinput(), soundcard_setoutput(), and soundcard_writeframe(). 00610 { 00611 int res; 00612 static char sizbuf[8000]; 00613 static int sizpos = 0; 00614 int len = sizpos; 00615 int pos; 00616 /* Immediately return if no sound is enabled */ 00617 if (nosound) 00618 return 0; 00619 /* Stop any currently playing sound */ 00620 cursound = -1; 00621 if (!full_duplex && !playbackonly) { 00622 /* If we're half duplex, we have to switch to read mode 00623 to honor immediate needs if necessary. But if we are in play 00624 back only mode, then we don't switch because the console 00625 is only being used one way -- just to playback something. */ 00626 res = soundcard_setinput(1); 00627 if (res < 0) { 00628 ast_log(LOG_WARNING, "Unable to set device to input mode\n"); 00629 return -1; 00630 } 00631 return 0; 00632 } 00633 res = soundcard_setoutput(0); 00634 if (res < 0) { 00635 ast_log(LOG_WARNING, "Unable to set output device\n"); 00636 return -1; 00637 } else if (res > 0) { 00638 /* The device is still in read mode, and it's too soon to change it, 00639 so just pretend we wrote it */ 00640 return 0; 00641 } 00642 /* We have to digest the frame in 160-byte portions */ 00643 if (f->datalen > sizeof(sizbuf) - sizpos) { 00644 ast_log(LOG_WARNING, "Frame too large\n"); 00645 return -1; 00646 } 00647 memcpy(sizbuf + sizpos, f->data, f->datalen); 00648 len += f->datalen; 00649 pos = 0; 00650 while(len - pos > FRAME_SIZE * 2) { 00651 soundcard_writeframe((short *)(sizbuf + pos)); 00652 pos += FRAME_SIZE * 2; 00653 } 00654 if (len - pos) 00655 memmove(sizbuf, sizbuf + pos, len - pos); 00656 sizpos = len - pos; 00657 return 0; 00658 }
|
|
Definition at line 217 of file chan_oss_old.c. References ast_log(), sound::datalen, FRAME_SIZE, LOG_WARNING, sound::silencelen, sounddev, sounds, and total. 00218 { 00219 short myframe[FRAME_SIZE]; 00220 int total = FRAME_SIZE; 00221 short *frame = NULL; 00222 int amt=0; 00223 int res; 00224 int myoff; 00225 audio_buf_info abi; 00226 if (cursound > -1) { 00227 res = ioctl(sounddev, SNDCTL_DSP_GETOSPACE ,&abi); 00228 if (res) { 00229 ast_log(LOG_WARNING, "Unable to read output space\n"); 00230 return -1; 00231 } 00232 /* Calculate how many samples we can send, max */ 00233 if (total > (abi.fragments * abi.fragsize / 2)) 00234 total = abi.fragments * abi.fragsize / 2; 00235 res = total; 00236 if (sampsent < sounds[cursound].samplen) { 00237 myoff=0; 00238 while(total) { 00239 amt = total; 00240 if (amt > (sounds[cursound].datalen - offset)) 00241 amt = sounds[cursound].datalen - offset; 00242 memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2); 00243 total -= amt; 00244 offset += amt; 00245 sampsent += amt; 00246 myoff += amt; 00247 if (offset >= sounds[cursound].datalen) 00248 offset = 0; 00249 } 00250 /* Set it up for silence */ 00251 if (sampsent >= sounds[cursound].samplen) 00252 silencelen = sounds[cursound].silencelen; 00253 frame = myframe; 00254 } else { 00255 if (silencelen > 0) { 00256 frame = silence; 00257 silencelen -= res; 00258 } else { 00259 if (sounds[cursound].repeat) { 00260 /* Start over */ 00261 sampsent = 0; 00262 offset = 0; 00263 } else { 00264 cursound = -1; 00265 nosound = 0; 00266 } 00267 } 00268 } 00269 if (frame) 00270 res = write(sounddev, frame, res * 2); 00271 if (res > 0) 00272 return 0; 00273 return res; 00274 } 00275 return 0; 00276 }
|
|
Definition at line 367 of file chan_oss_old.c. References ast_log(), ast_verbose(), BUFFER_FMT, fmt, full_duplex, LOG_WARNING, option_verbose, sounddev, and VERBOSE_PREFIX_2. 00368 { 00369 int fmt, desired, res, fd = sounddev; 00370 static int warnedalready = 0; 00371 static int warnedalready2 = 0; 00372 00373 #if __BYTE_ORDER == __LITTLE_ENDIAN 00374 fmt = AFMT_S16_LE; 00375 #else 00376 fmt = AFMT_S16_BE; 00377 #endif 00378 00379 res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); 00380 if (res < 0) { 00381 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n"); 00382 return -1; 00383 } 00384 res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); 00385 00386 /* Check to see if duplex set (FreeBSD Bug)*/ 00387 res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt); 00388 00389 if ((fmt & DSP_CAP_DUPLEX) && !res) { 00390 if (option_verbose > 1) 00391 ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n"); 00392 full_duplex = -1; 00393 } 00394 fmt = 0; 00395 res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt); 00396 if (res < 0) { 00397 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00398 return -1; 00399 } 00400 /* 8000 Hz desired */ 00401 desired = 8000; 00402 fmt = desired; 00403 res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt); 00404 if (res < 0) { 00405 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00406 return -1; 00407 } 00408 if (fmt != desired) { 00409 if (!warnedalready++) 00410 ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt); 00411 } 00412 #if 1 00413 fmt = BUFFER_FMT; 00414 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt); 00415 if (res < 0) { 00416 if (!warnedalready2++) 00417 ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n"); 00418 } 00419 #endif 00420 return 0; 00421 }
|
|
Definition at line 278 of file chan_oss_old.c. References ast_log(), ast_select(), LOG_WARNING, oss, chan_oss_pvt::owner, send_sound(), sndcmd, and sounddev. 00279 { 00280 fd_set rfds; 00281 fd_set wfds; 00282 int max; 00283 int res; 00284 char ign[4096]; 00285 if (read(sounddev, ign, sizeof(sounddev)) < 0) 00286 ast_log(LOG_WARNING, "Read error on sound device: %s\n", strerror(errno)); 00287 for(;;) { 00288 FD_ZERO(&rfds); 00289 FD_ZERO(&wfds); 00290 max = sndcmd[0]; 00291 FD_SET(sndcmd[0], &rfds); 00292 if (!oss.owner) { 00293 FD_SET(sounddev, &rfds); 00294 if (sounddev > max) 00295 max = sounddev; 00296 } 00297 if (cursound > -1) { 00298 FD_SET(sounddev, &wfds); 00299 if (sounddev > max) 00300 max = sounddev; 00301 } 00302 res = ast_select(max + 1, &rfds, &wfds, NULL, NULL); 00303 if (res < 1) { 00304 ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); 00305 continue; 00306 } 00307 if (FD_ISSET(sndcmd[0], &rfds)) { 00308 read(sndcmd[0], &cursound, sizeof(cursound)); 00309 silencelen = 0; 00310 offset = 0; 00311 sampsent = 0; 00312 } 00313 if (FD_ISSET(sounddev, &rfds)) { 00314 /* Ignore read */ 00315 if (read(sounddev, ign, sizeof(ign)) < 0) 00316 ast_log(LOG_WARNING, "Read error on sound device: %s\n", strerror(errno)); 00317 } 00318 if (FD_ISSET(sounddev, &wfds)) 00319 if (send_sound()) 00320 ast_log(LOG_WARNING, "Failed to write sound\n"); 00321 } 00322 /* Never reached */ 00323 return NULL; 00324 }
|
|
Definition at line 482 of file chan_oss_old.c. References ast_log(), DEV_DSP, full_duplex, LOG_WARNING, setformat(), soundcard_setinput(), and sounddev. 00483 { 00484 /* Assume it's full duplex for starters */ 00485 int fd = open(DEV_DSP, O_RDWR | O_NONBLOCK); 00486 if (fd < 0) { 00487 ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno)); 00488 return fd; 00489 } 00490 gettimeofday(&lasttime, NULL); 00491 sounddev = fd; 00492 setformat(); 00493 if (!full_duplex) 00494 soundcard_setinput(1); 00495 return sounddev; 00496 }
|
|
Definition at line 454 of file chan_oss_old.c. References ast_log(), DEV_DSP, full_duplex, LOG_WARNING, readmode, setformat(), sounddev, and time_has_passed(). Referenced by oss_read(), oss_write(), and soundcard_init(). 00455 { 00456 int fd = sounddev; 00457 if (full_duplex || (readmode && !force)) 00458 return 0; 00459 readmode = -1; 00460 if (force || time_has_passed()) { 00461 ioctl(sounddev, SNDCTL_DSP_RESET, 0); 00462 close(sounddev); 00463 /* dup2(0, sound); */ 00464 fd = open(DEV_DSP, O_RDONLY | O_NONBLOCK); 00465 if (fd < 0) { 00466 ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno)); 00467 return -1; 00468 } 00469 /* dup2 will close the original and make fd be sound */ 00470 if (dup2(fd, sounddev) < 0) { 00471 ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno)); 00472 return -1; 00473 } 00474 if (setformat()) { 00475 return -1; 00476 } 00477 return 0; 00478 } 00479 return 1; 00480 }
|
|
Definition at line 423 of file chan_oss_old.c. References ast_log(), DEV_DSP, full_duplex, LOG_WARNING, readmode, setformat(), sounddev, and time_has_passed(). Referenced by oss_write(). 00424 { 00425 /* Make sure the soundcard is in output mode. */ 00426 int fd = sounddev; 00427 if (full_duplex || (!readmode && !force)) 00428 return 0; 00429 readmode = 0; 00430 if (force || time_has_passed()) { 00431 ioctl(sounddev, SNDCTL_DSP_RESET, 0); 00432 /* Keep the same fd reserved by closing the sound device and copying stdin at the same 00433 time. */ 00434 /* dup2(0, sound); */ 00435 close(sounddev); 00436 fd = open(DEV_DSP, O_WRONLY |O_NONBLOCK); 00437 if (fd < 0) { 00438 ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno)); 00439 return -1; 00440 } 00441 /* dup2 will close the original and make fd be sound */ 00442 if (dup2(fd, sounddev) < 0) { 00443 ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno)); 00444 return -1; 00445 } 00446 if (setformat()) { 00447 return -1; 00448 } 00449 return 0; 00450 } 00451 return 1; 00452 }
|
|
Definition at line 574 of file chan_oss_old.c. References ast_log(), buffersize, FRAME_SIZE, LOG_WARNING, MAX_BUFFER_SIZE, and sounddev. 00575 { 00576 /* Write an exactly FRAME_SIZE sized of frame */ 00577 static int bufcnt = 0; 00578 static short buffer[FRAME_SIZE * MAX_BUFFER_SIZE * 5]; 00579 struct audio_buf_info info; 00580 int res; 00581 int fd = sounddev; 00582 static int warned=0; 00583 if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)) { 00584 if (!warned) 00585 ast_log(LOG_WARNING, "Error reading output space\n"); 00586 bufcnt = buffersize; 00587 warned++; 00588 } 00589 if ((info.fragments >= buffersize * 5) && (bufcnt == buffersize)) { 00590 /* We've run out of stuff, buffer again */ 00591 bufcnt = 0; 00592 } 00593 if (bufcnt == buffersize) { 00594 /* Write sample immediately */ 00595 res = write(fd, ((void *)data), FRAME_SIZE * 2); 00596 } else { 00597 /* Copy the data into our buffer */ 00598 res = FRAME_SIZE * 2; 00599 memcpy(buffer + (bufcnt * FRAME_SIZE), data, FRAME_SIZE * 2); 00600 bufcnt++; 00601 if (bufcnt == buffersize) { 00602 res = write(fd, ((void *)buffer), FRAME_SIZE * 2 * buffersize); 00603 } 00604 } 00605 return res; 00606 }
|
|
Definition at line 164 of file chan_oss_old.c. References MIN_SWITCH_TIME. Referenced by soundcard_setinput(), and soundcard_setoutput(). 00165 { 00166 struct timeval tv; 00167 int ms; 00168 gettimeofday(&tv, NULL); 00169 ms = (tv.tv_sec - lasttime.tv_sec) * 1000 + 00170 (tv.tv_usec - lasttime.tv_usec) / 1000; 00171 if (ms > MIN_SWITCH_TIME) 00172 return -1; 00173 return 0; 00174 }
|
|
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).
Definition at line 1100 of file chan_oss_old.c. References ast_channel_unregister(), ast_cli_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, myclis, oss, oss_tech, chan_oss_pvt::owner, sndcmd, and sounddev. 01101 { 01102 int x; 01103 01104 ast_channel_unregister(&oss_tech); 01105 for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++) 01106 ast_cli_unregister(myclis + x); 01107 close(sounddev); 01108 if (sndcmd[0] > 0) { 01109 close(sndcmd[0]); 01110 close(sndcmd[1]); 01111 } 01112 if (oss.owner) 01113 ast_softhangup(oss.owner, AST_SOFTHANGUP_APPUNLOAD); 01114 if (oss.owner) 01115 return -1; 01116 return 0; 01117 }
|
|
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.
Definition at line 1124 of file chan_oss_old.c. 01125 { 01126 return usecnt; 01127 }
|
|
Initial value: "Usage: answer\n" " Answers an incoming call on the console (OSS) channel.\n" Definition at line 909 of file chan_oss_old.c. |
|
Definition at line 193 of file chan_oss_old.c. |
|
Initial value: "Usage: autoanswer [on|off]\n" " Enables or disables autoanswer feature. If used without\n" " argument, displays the current on/off status of autoanswer.\n" " The default value of autoanswer is in 'oss.conf'.\n" Definition at line 855 of file chan_oss_old.c. |
|
Definition at line 183 of file chan_oss_old.c. Referenced by soundcard_writeframe(). |
|
Definition at line 99 of file chan_oss_old.c. |
|
Definition at line 101 of file chan_oss_old.c. |
|
Definition at line 211 of file chan_oss_old.c. |
|
Definition at line 97 of file chan_oss_old.c. |
|
Initial value: "Usage: dial [extension[@context]]\n" " Dials a given extensison (and context if specified)\n" Definition at line 998 of file chan_oss_old.c. |
|
Definition at line 103 of file chan_oss_old.c. |
|
Initial value: "Usage: flash\n" " Flashes the call currently placed on the console.\n" Definition at line 951 of file chan_oss_old.c. |
|
Definition at line 185 of file chan_oss_old.c. Referenced by load_module(), oss_write(), setformat(), soundcard_init(), soundcard_setinput(), and soundcard_setoutput(). |
|
Initial value: "Usage: hangup\n" " Hangs up any call currently placed on the console.\n" Definition at line 946 of file chan_oss_old.c. |
|
Definition at line 105 of file chan_oss_old.c. |
|
Definition at line 102 of file chan_oss_old.c. |
|
Definition at line 86 of file chan_oss_old.c. |
|
Definition at line 1035 of file chan_oss_old.c. |
|
Definition at line 215 of file chan_oss_old.c. |
|
Definition at line 214 of file chan_oss_old.c. |
|
Referenced by console_answer(), console_dial(), console_flash(), console_hangup(), console_sendtext(), console_transfer(), oss_hangup(), oss_request(), sound_thread(), and unload_module(). |
|
Definition at line 148 of file chan_oss_old.c. |
|
Definition at line 91 of file chan_oss_old.c. |
|
Definition at line 188 of file chan_oss_old.c. Referenced by soundcard_setinput(), and soundcard_setoutput(). |
|
Definition at line 212 of file chan_oss_old.c. |
|
Initial value: "Usage: send text <message>\n" " Sends a text message for display on the remote terminal.\n" Definition at line 877 of file chan_oss_old.c. |
|
Definition at line 107 of file chan_oss_old.c. |
|
Definition at line 213 of file chan_oss_old.c. |
|
Definition at line 89 of file chan_oss_old.c. |
|
Definition at line 90 of file chan_oss_old.c. |
|
Definition at line 127 of file chan_oss_old.c. |
|
Definition at line 191 of file chan_oss_old.c. Referenced by oss_new(), oss_read(), send_sound(), setformat(), sound_thread(), soundcard_init(), soundcard_setinput(), soundcard_setoutput(), soundcard_writeframe(), and unload_module(). |
|
Definition at line 118 of file chan_oss_old.c. |
|
Definition at line 180 of file chan_oss_old.c. |
|
Definition at line 98 of file chan_oss_old.c. |
|
Initial value: "Usage: transfer <extension>[@context]\n" " Transfers the currently connected call to the given extension (and\n" "context if specified)\n" Definition at line 1030 of file chan_oss_old.c. |
|
Definition at line 96 of file chan_oss_old.c. |
|
Definition at line 88 of file chan_oss_old.c. |