![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
chan_oss.c File Reference
Luigi Rizzo
Definition in file chan_oss.c.
#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/time.h>
#include <stdlib.h>
#include <errno.h>
#include <soundcard.h>
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/callerid.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 "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "busy.h"
#include "ringtone.h"
#include "ring10.h"
#include "answer.h"
Include dependency graph for chan_oss.c:

Go to the source code of this file.
Data Structures | |
| struct | chan_oss_pvt |
| descriptor for one of our channels. More... | |
| struct | sound |
Defines | |
| #define | BOOST_MAX 40 |
| #define | BOOST_SCALE (1<<9) |
| #define | DEV_DSP "/dev/dsp" |
| #define | FRAGS ( ( (6 * 5) << 16 ) | 0x6 ) |
| #define | FRAME_SIZE 160 |
| #define | M_BOOL(tag, dst) M_F(tag, (dst) = ast_true(__val) ) |
| #define | M_END(x) x; |
| #define | M_F(tag, f) if (!strcasecmp((__s), tag)) { f; } else |
| #define | M_START(var, val) char *__s = var; char *__val = val; |
| #define | M_STR(tag, dst) M_F(tag, ast_copy_string(dst, __val, sizeof(dst))) |
| #define | M_UINT(tag, dst) M_F(tag, (dst) = strtoul(__val, NULL, 0) ) |
| #define | MAX(a, b) ((a) > (b) ? (a) : (b)) |
| #define | MIN(a, b) ((a) < (b) ? (a) : (b)) |
| #define | O_CLOSE 0x444 |
| #define | QUEUE_SIZE 10 |
| #define | TEXT_SIZE 256 |
| #define | WARN_frag 4 |
| #define | WARN_speed 2 |
| #define | WARN_used_blocks 1 |
Functions | |
| static char * | ast_ext_ctx (const char *src, char **ext, char **ctx) |
| AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"OSS Console Channel Driver") | |
| static int | console_active (int fd, int argc, char *argv[]) |
| static char * | console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| answer command from the console | |
| static char * | console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Console send text CLI command. | |
| static int | console_transfer (int fd, int argc, char *argv[]) |
| static int | do_boost (int fd, int argc, char *argv[]) |
| static struct chan_oss_pvt * | find_desc (char *dev) |
| returns a pointer to the descriptor with the given name | |
| static int | load_module (void) |
| static int | oss_answer (struct ast_channel *c) |
| remote side answered the phone | |
| static int | oss_call (struct ast_channel *c, char *dest, int timeout) |
| handler for incoming calls. Either autoanswer, or start ringing | |
| static int | oss_digit_begin (struct ast_channel *c, char digit) |
| static int | oss_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
| 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, const void *data, size_t datalen) |
| static struct ast_channel * | oss_new (struct chan_oss_pvt *o, char *ext, char *ctx, int state) |
| allocate a new channel. | |
| 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 *c, struct ast_frame *f) |
| used for data coming from the network | |
| static void | ring (struct chan_oss_pvt *o, int x) |
| Play ringtone 'x' on device 'o'. | |
| static void | send_sound (struct chan_oss_pvt *o) |
| Handler for 'sound writable' events from the sound thread. | |
| static int | setformat (struct chan_oss_pvt *o, int mode) |
| static void * | sound_thread (void *arg) |
| static int | soundcard_writeframe (struct chan_oss_pvt *o, short *data) |
| static void | store_boost (struct chan_oss_pvt *o, char *s) |
| store the boost factor | |
| static void | store_callerid (struct chan_oss_pvt *o, char *s) |
| static struct chan_oss_pvt * | store_config (struct ast_config *cfg, char *ctg) |
| static void | store_mixer (struct chan_oss_pvt *o, char *s) |
| static int | unload_module (void) |
| static int | used_blocks (struct chan_oss_pvt *o) |
| Returns the number of blocks used in the audio output channel. | |
Variables | |
| static const char | active_usage [] |
| static struct ast_cli_entry | cli_oss [] |
| static char * | config = "oss.conf" |
| static struct ast_jb_conf | default_jbconf |
| static struct ast_jb_conf | global_jbconf |
| static char * | oss_active |
| static int | oss_debug |
| static struct chan_oss_pvt | oss_default |
| static const struct ast_channel_tech | oss_tech |
| static struct sound | sounds [] |
| static char | tdesc [] = "OSS Console Channel Driver" |
| static const char | transfer_usage [] |
|
|
slightly less than 7 bits Definition at line 362 of file chan_oss.c. Referenced by store_boost(). |
|
|
boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must be representable in 16 bits to avoid overflows. Definition at line 361 of file chan_oss.c. Referenced by do_boost(), oss_read(), and store_boost(). |
|
|
Definition at line 275 of file chan_oss.c. |
|
|
Definition at line 258 of file chan_oss.c. |
|
|
Definition at line 252 of file chan_oss.c. |
|
|
Definition at line 218 of file chan_oss.c. Referenced by store_config(). |
|
|
Definition at line 216 of file chan_oss.c. Referenced by store_config(). |
|
|
Definition at line 217 of file chan_oss.c. Referenced by store_config(). |
|
|
Definition at line 214 of file chan_oss.c. Referenced by store_config(). |
|
|
Definition at line 220 of file chan_oss.c. Referenced by store_config(). |
|
|
Definition at line 219 of file chan_oss.c. Referenced by store_config(). |
|
|
Definition at line 282 of file chan_oss.c. |
|
|
Definition at line 279 of file chan_oss.c. |
|
|
Definition at line 270 of file chan_oss.c. Referenced by console_hangup(), oss_hangup(), setformat(), and sound_thread(). |
|
|
Definition at line 253 of file chan_oss.c. |
|
|
Definition at line 265 of file chan_oss.c. Referenced by console_sendtext(). |
|
|
Definition at line 351 of file chan_oss.c. Referenced by setformat(). |
|
|
Definition at line 350 of file chan_oss.c. Referenced by setformat(). |
|
|
Definition at line 349 of file chan_oss.c. Referenced by used_blocks(). |
|
||||||||||||||||
|
Definition at line 466 of file chan_oss.c. References ast_strdup, find_desc(), and chan_oss_pvt::overridecontext. Referenced by console_transfer(). 00467 { 00468 struct chan_oss_pvt *o = find_desc(oss_active); 00469 00470 if (ext == NULL || ctx == NULL) 00471 return NULL; /* error */ 00472 00473 *ext = *ctx = NULL; 00474 00475 if (src && *src != '\0') 00476 *ext = ast_strdup(src); 00477 00478 if (*ext == NULL) 00479 return NULL; 00480 00481 if (!o->overridecontext) { 00482 /* parse from the right */ 00483 *ctx = strrchr(*ext, '@'); 00484 if (*ctx) 00485 *(*ctx)++ = '\0'; 00486 } 00487 00488 return *ext; 00489 }
|
|
||||||||||||
|
|
|
||||||||||||||||
|
Definition at line 1378 of file chan_oss.c. References ast_cli(), find_desc(), chan_oss_pvt::name, chan_oss_pvt::next, oss_default, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 01379 { 01380 if (argc == 2) 01381 ast_cli(fd, "active console is [%s]\n", oss_active); 01382 else if (argc != 3) 01383 return RESULT_SHOWUSAGE; 01384 else { 01385 struct chan_oss_pvt *o; 01386 if (strcmp(argv[2], "show") == 0) { 01387 for (o = oss_default.next; o; o = o->next) 01388 ast_cli(fd, "device [%s] exists\n", o->name); 01389 return RESULT_SUCCESS; 01390 } 01391 o = find_desc(argv[2]); 01392 if (o == NULL) 01393 ast_cli(fd, "No device [%s] exists\n", argv[2]); 01394 else 01395 oss_active = o->name; 01396 } 01397 return RESULT_SUCCESS; 01398 }
|
|
||||||||||||||||
|
answer command from the console
Definition at line 1142 of file chan_oss.c. References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, chan_oss_pvt::cursound, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::nosound, chan_oss_pvt::owner, and ast_cli_entry::usage. 01143 { 01144 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 01145 struct chan_oss_pvt *o = find_desc(oss_active); 01146 01147 switch (cmd) { 01148 case CLI_INIT: 01149 e->command = "console answer"; 01150 e->usage = 01151 "Usage: console answer\n" 01152 " Answers an incoming call on the console (OSS) channel.\n"; 01153 return NULL; 01154 01155 case CLI_GENERATE: 01156 return NULL; /* no completion */ 01157 } 01158 if (a->argc != e->args) 01159 return CLI_SHOWUSAGE; 01160 if (!o->owner) { 01161 ast_cli(a->fd, "No one is calling us\n"); 01162 return CLI_FAILURE; 01163 } 01164 o->hookstate = 1; 01165 o->cursound = -1; 01166 o->nosound = 0; 01167 ast_queue_frame(o->owner, &f); 01168 return CLI_SUCCESS; 01169 }
|
|
||||||||||||||||
|
Definition at line 1101 of file chan_oss.c. References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_log(), chan_oss_pvt::autoanswer, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), LOG_WARNING, and ast_cli_entry::usage. 01102 { 01103 struct chan_oss_pvt *o = find_desc(oss_active); 01104 01105 switch (cmd) { 01106 case CLI_INIT: 01107 e->command = "console autoanswer [on|off]"; 01108 e->usage = 01109 "Usage: console autoanswer [on|off]\n" 01110 " Enables or disables autoanswer feature. If used without\n" 01111 " argument, displays the current on/off status of autoanswer.\n" 01112 " The default value of autoanswer is in 'oss.conf'.\n"; 01113 return NULL; 01114 01115 case CLI_GENERATE: 01116 return NULL; 01117 } 01118 01119 if (a->argc == e->args - 1) { 01120 ast_cli(a->fd, "Auto answer is %s.\n", o->autoanswer ? "on" : "off"); 01121 return CLI_SUCCESS; 01122 } 01123 if (a->argc != e->args) 01124 return CLI_SHOWUSAGE; 01125 if (o == NULL) { 01126 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n", 01127 oss_active); 01128 return CLI_FAILURE; 01129 } 01130 if (!strcasecmp(a->argv[e->args-1], "on")) 01131 o->autoanswer = 1; 01132 else if (!strcasecmp(a->argv[e->args - 1], "off")) 01133 o->autoanswer = 0; 01134 else 01135 return CLI_SHOWUSAGE; 01136 return CLI_SUCCESS; 01137 }
|
|
||||||||||||||||
|
Definition at line 1267 of file chan_oss.c. References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_DTMF, ast_queue_frame(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), chan_oss_pvt::owner, s, ast_frame::subclass, and ast_cli_entry::usage. 01268 { 01269 char *s = NULL, *mye = NULL, *myc = NULL; 01270 struct chan_oss_pvt *o = find_desc(oss_active); 01271 01272 if (cmd == CLI_INIT) { 01273 e->command = "console dial"; 01274 e->usage = 01275 "Usage: console dial [extension[@context]]\n" 01276 " Dials a given extension (and context if specified)\n"; 01277 return NULL; 01278 } else if (cmd == CLI_GENERATE) 01279 return NULL; 01280 01281 if (a->argc > e->args + 1) 01282 return CLI_SHOWUSAGE; 01283 if (o->owner) { /* already in a call */ 01284 int i; 01285 struct ast_frame f = { AST_FRAME_DTMF, 0 }; 01286 01287 if (a->argc == e->args) { /* argument is mandatory here */ 01288 ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n"); 01289 return CLI_FAILURE; 01290 } 01291 s = a->argv[e->args]; 01292 /* send the string one char at a time */ 01293 for (i = 0; i < strlen(s); i++) { 01294 f.subclass = s[i]; 01295 ast_queue_frame(o->owner, &f); 01296 } 01297 return CLI_SUCCESS; 01298 } 01299 /* if we have an argument split it into extension and context */ 01300 if (a->argc == e->args + 1) 01301 s = ast_ext_ctx(a->argv[e->args], &mye, &myc); 01302 /* supply default values if needed */ 01303 if (mye == NULL) 01304 mye = o->ext; 01305 if (myc == NULL) 01306 myc = o->ctx; 01307 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01308 o->hookstate = 1; 01309 oss_new(o, mye, myc, AST_STATE_RINGING); 01310 } else 01311 ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc); 01312 if (s) 01313 free(s); 01314 return CLI_SUCCESS; 01315 }
|
|
||||||||||||||||
|
Definition at line 1239 of file chan_oss.c. References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CONTROL_FLASH, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, chan_oss_pvt::cursound, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::nosound, chan_oss_pvt::owner, and ast_cli_entry::usage. 01240 { 01241 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH }; 01242 struct chan_oss_pvt *o = find_desc(oss_active); 01243 01244 if (cmd == CLI_INIT) { 01245 e->command = "console flash"; 01246 e->usage = 01247 "Usage: console flash\n" 01248 " Flashes the call currently placed on the console.\n"; 01249 return NULL; 01250 } else if (cmd == CLI_GENERATE) 01251 return NULL; 01252 01253 if (a->argc != e->args) 01254 return CLI_SHOWUSAGE; 01255 o->cursound = -1; 01256 o->nosound = 0; /* when cursound is -1 nosound must be 0 */ 01257 if (!o->owner) { /* XXX maybe !o->hookstate too ? */ 01258 ast_cli(a->fd, "No call to flash\n"); 01259 return CLI_FAILURE; 01260 } 01261 o->hookstate = 0; 01262 if (o->owner) /* XXX must be true, right ? */ 01263 ast_queue_frame(o->owner, &f); 01264 return CLI_SUCCESS; 01265 }
|
|
||||||||||||||||
|
Definition at line 1211 of file chan_oss.c. References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), ast_queue_hangup(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, chan_oss_pvt::cursound, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::nosound, O_CLOSE, chan_oss_pvt::owner, setformat(), and ast_cli_entry::usage. 01212 { 01213 struct chan_oss_pvt *o = find_desc(oss_active); 01214 01215 if (cmd == CLI_INIT) { 01216 e->command = "console hangup"; 01217 e->usage = 01218 "Usage: console hangup\n" 01219 " Hangs up any call currently placed on the console.\n"; 01220 return NULL; 01221 } else if (cmd == CLI_GENERATE) 01222 return NULL; 01223 01224 if (a->argc != e->args) 01225 return CLI_SHOWUSAGE; 01226 o->cursound = -1; 01227 o->nosound = 0; 01228 if (!o->owner && !o->hookstate) { /* XXX maybe only one ? */ 01229 ast_cli(a->fd, "No call to hang up\n"); 01230 return CLI_FAILURE; 01231 } 01232 o->hookstate = 0; 01233 if (o->owner) 01234 ast_queue_hangup(o->owner); 01235 setformat(o, O_CLOSE); 01236 return CLI_SUCCESS; 01237 }
|
|
||||||||||||||||
|
Definition at line 1317 of file chan_oss.c. References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, find_desc(), chan_oss_pvt::mute, s, and ast_cli_entry::usage. 01318 { 01319 struct chan_oss_pvt *o = find_desc(oss_active); 01320 char *s; 01321 01322 if (cmd == CLI_INIT) { 01323 e->command = "console {mute|unmute}"; 01324 e->usage = 01325 "Usage: console {mute|unmute}\n" 01326 " Mute/unmute the microphone.\n"; 01327 return NULL; 01328 } else if (cmd == CLI_GENERATE) 01329 return NULL; 01330 01331 if (a->argc != e->args) 01332 return CLI_SHOWUSAGE; 01333 s = a->argv[e->args-1]; 01334 if (!strcasecmp(s, "mute")) 01335 o->mute = 1; 01336 else if (!strcasecmp(s, "unmute")) 01337 o->mute = 0; 01338 else 01339 return CLI_SHOWUSAGE; 01340 return CLI_SUCCESS; 01341 }
|
|
||||||||||||||||
|
Console send text CLI command.
Definition at line 1177 of file chan_oss.c. References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_TEXT, ast_join(), ast_queue_frame(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_frame::data, ast_frame::datalen, ast_cli_args::fd, find_desc(), ast_frame::frametype, chan_oss_pvt::owner, ast_frame::subclass, TEXT_SIZE, and ast_cli_entry::usage. 01178 { 01179 struct chan_oss_pvt *o = find_desc(oss_active); 01180 char buf[TEXT_SIZE]; 01181 01182 if (cmd == CLI_INIT) { 01183 e->command = "console send text"; 01184 e->usage = 01185 "Usage: console send text <message>\n" 01186 " Sends a text message for display on the remote terminal.\n"; 01187 return NULL; 01188 } else if (cmd == CLI_GENERATE) 01189 return NULL; 01190 01191 if (a->argc < e->args + 1) 01192 return CLI_SHOWUSAGE; 01193 if (!o->owner) { 01194 ast_cli(a->fd, "Not in a call\n"); 01195 return CLI_FAILURE; 01196 } 01197 ast_join(buf, sizeof(buf) - 1, a->argv + e->args); 01198 if (!ast_strlen_zero(buf)) { 01199 struct ast_frame f = { 0, }; 01200 int i = strlen(buf); 01201 buf[i] = '\n'; 01202 f.frametype = AST_FRAME_TEXT; 01203 f.subclass = 0; 01204 f.data = buf; 01205 f.datalen = i + 1; 01206 ast_queue_frame(o->owner, &f); 01207 } 01208 return CLI_SUCCESS; 01209 }
|
|
||||||||||||||||
|
Definition at line 1343 of file chan_oss.c. References ast_async_goto(), ast_bridged_channel(), ast_cli(), ast_exists_extension(), ast_ext_ctx(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ext, find_desc(), free, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 01344 { 01345 struct chan_oss_pvt *o = find_desc(oss_active); 01346 struct ast_channel *b = NULL; 01347 char *tmp, *ext, *ctx; 01348 01349 if (argc != 3) 01350 return RESULT_SHOWUSAGE; 01351 if (o == NULL) 01352 return RESULT_FAILURE; 01353 if (o->owner == NULL || (b = ast_bridged_channel(o->owner)) == NULL) { 01354 ast_cli(fd, "There is no call to transfer\n"); 01355 return RESULT_SUCCESS; 01356 } 01357 01358 tmp = ast_ext_ctx(argv[2], &ext, &ctx); 01359 if (ctx == NULL) /* supply default context if needed */ 01360 ctx = o->owner->context; 01361 if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num)) 01362 ast_cli(fd, "No such extension exists\n"); 01363 else { 01364 ast_cli(fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx); 01365 if (ast_async_goto(b, ctx, ext, 1)) 01366 ast_cli(fd, "Failed to transfer :(\n"); 01367 } 01368 if (tmp) 01369 free(tmp); 01370 return RESULT_SUCCESS; 01371 }
|
|
||||||||||||||||
|
Definition at line 1428 of file chan_oss.c. References ast_cli(), chan_oss_pvt::boost, BOOST_SCALE, find_desc(), RESULT_SUCCESS, and store_boost(). 01429 { 01430 struct chan_oss_pvt *o = find_desc(oss_active); 01431 01432 if (argc == 2) 01433 ast_cli(fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE))); 01434 else if (argc == 3) 01435 store_boost(o, argv[2]); 01436 return RESULT_SUCCESS; 01437 }
|
|
|
returns a pointer to the descriptor with the given name
Definition at line 440 of file chan_oss.c. References ast_log(), LOG_WARNING, chan_oss_pvt::name, chan_oss_pvt::next, and oss_default. Referenced by ast_ext_ctx(), console_active(), console_answer(), console_autoanswer(), console_dial(), console_flash(), console_hangup(), console_mute(), console_sendtext(), console_transfer(), do_boost(), load_module(), and oss_request(). 00441 { 00442 struct chan_oss_pvt *o = NULL; 00443 00444 if (!dev) 00445 ast_log(LOG_WARNING, "null dev\n"); 00446 00447 for (o = oss_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next); 00448 00449 if (!o) 00450 ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--"); 00451 00452 return o; 00453 }
|
|
|
Definition at line 1585 of file chan_oss.c. References ast_category_browse(), ast_channel_register(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, cli_oss, default_jbconf, find_desc(), global_jbconf, LOG_ERROR, LOG_NOTICE, oss_tech, and store_config(). 01586 { 01587 struct ast_config *cfg = NULL; 01588 char *ctg = NULL; 01589 01590 /* Copy the default jb config over global_jbconf */ 01591 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01592 01593 /* load config file */ 01594 if (!(cfg = ast_config_load(config))) { 01595 ast_log(LOG_NOTICE, "Unable to load config %s\n", config); 01596 return AST_MODULE_LOAD_DECLINE; 01597 } 01598 01599 do { 01600 store_config(cfg, ctg); 01601 } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL); 01602 01603 ast_config_destroy(cfg); 01604 01605 if (find_desc(oss_active) == NULL) { 01606 ast_log(LOG_NOTICE, "Device %s not found\n", oss_active); 01607 /* XXX we could default to 'dsp' perhaps ? */ 01608 /* XXX should cleanup allocated memory etc. */ 01609 return AST_MODULE_LOAD_FAILURE; 01610 } 01611 01612 if (ast_channel_register(&oss_tech)) { 01613 ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n"); 01614 return AST_MODULE_LOAD_FAILURE; 01615 } 01616 01617 ast_cli_register_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry)); 01618 01619 return AST_MODULE_LOAD_SUCCESS; 01620 }
|
|
|
remote side answered the phone
Definition at line 844 of file chan_oss.c. References AST_CONTROL_ANSWER, ast_setstate(), AST_STATE_UP, ast_verbose(), chan_oss_pvt::cursound, chan_oss_pvt::nosound, ring(), and ast_channel::tech_pvt. 00845 { 00846 struct chan_oss_pvt *o = c->tech_pvt; 00847 00848 ast_verbose(" << Console call has been answered >> \n"); 00849 #if 0 00850 /* play an answer tone (XXX do we really need it ?) */ 00851 ring(o, AST_CONTROL_ANSWER); 00852 #endif 00853 ast_setstate(c, AST_STATE_UP); 00854 o->cursound = -1; 00855 o->nosound = 0; 00856 return 0; 00857 }
|
|
||||||||||||||||
|
handler for incoming calls. Either autoanswer, or start ringing
Definition at line 804 of file chan_oss.c. References AST_APP_ARG, AST_CONTROL_ANSWER, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_DECLARE_APP_ARGS, AST_FRAME_CONTROL, AST_NONSTANDARD_APP_ARGS, ast_queue_frame(), ast_strdupa, ast_strlen_zero(), ast_verbose(), chan_oss_pvt::autoanswer, ast_channel::cid, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_rdnis, ast_frame::frametype, name, parse(), ring(), ast_frame::subclass, and ast_channel::tech_pvt. 00805 { 00806 struct chan_oss_pvt *o = c->tech_pvt; 00807 struct ast_frame f = { 0, }; 00808 AST_DECLARE_APP_ARGS(args, 00809 AST_APP_ARG(name); 00810 AST_APP_ARG(flags); 00811 ); 00812 char *parse = ast_strdupa(dest); 00813 00814 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 00815 00816 ast_verbose(" << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >>\n", dest, c->cid.cid_dnid, c->cid.cid_rdnis, c->cid.cid_name, c->cid.cid_num); 00817 if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "answer") == 0) { 00818 f.frametype = AST_FRAME_CONTROL; 00819 f.subclass = AST_CONTROL_ANSWER; 00820 ast_queue_frame(c, &f); 00821 } else if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "noanswer") == 0) { 00822 f.frametype = AST_FRAME_CONTROL; 00823 f.subclass = AST_CONTROL_RINGING; 00824 ast_queue_frame(c, &f); 00825 ring(o, AST_CONTROL_RING); 00826 } else if (o->autoanswer) { 00827 ast_verbose(" << Auto-answered >> \n"); 00828 f.frametype = AST_FRAME_CONTROL; 00829 f.subclass = AST_CONTROL_ANSWER; 00830 ast_queue_frame(c, &f); 00831 } else { 00832 ast_verbose("<< Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00833 f.frametype = AST_FRAME_CONTROL; 00834 f.subclass = AST_CONTROL_RINGING; 00835 ast_queue_frame(c, &f); 00836 ring(o, AST_CONTROL_RING); 00837 } 00838 return 0; 00839 }
|
|
||||||||||||
|
Definition at line 774 of file chan_oss.c.
|
|
||||||||||||||||
|
Definition at line 779 of file chan_oss.c. References ast_verbose(). 00780 { 00781 /* no better use for received digits than print them */ 00782 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00783 digit, duration); 00784 return 0; 00785 }
|
|
||||||||||||
|
Definition at line 968 of file chan_oss.c. References chan_oss_pvt::owner, and ast_channel::tech_pvt. 00969 { 00970 struct chan_oss_pvt *o = newchan->tech_pvt; 00971 o->owner = newchan; 00972 return 0; 00973 }
|
|
|
Definition at line 859 of file chan_oss.c. References AST_CONTROL_CONGESTION, ast_module_unref(), ast_verbose(), chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, chan_oss_pvt::cursound, chan_oss_pvt::hookstate, chan_oss_pvt::nosound, O_CLOSE, chan_oss_pvt::owner, ring(), setformat(), and ast_channel::tech_pvt. 00860 { 00861 struct chan_oss_pvt *o = c->tech_pvt; 00862 00863 o->cursound = -1; 00864 o->nosound = 0; 00865 c->tech_pvt = NULL; 00866 o->owner = NULL; 00867 ast_verbose(" << Hangup on console >> \n"); 00868 ast_module_unref(ast_module_info->self); 00869 if (o->hookstate) { 00870 if (o->autoanswer || o->autohangup) { 00871 /* Assume auto-hangup too */ 00872 o->hookstate = 0; 00873 setformat(o, O_CLOSE); 00874 } else { 00875 /* Make congestion noise */ 00876 ring(o, AST_CONTROL_CONGESTION); 00877 } 00878 } 00879 return 0; 00880 }
|
|
||||||||||||||||||||
|
Definition at line 975 of file chan_oss.c. References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_verbose(), chan_oss_pvt::cursound, LOG_WARNING, chan_oss_pvt::mohinterpret, chan_oss_pvt::nosound, ring(), and ast_channel::tech_pvt. 00976 { 00977 struct chan_oss_pvt *o = c->tech_pvt; 00978 int res = -1; 00979 00980 switch (cond) { 00981 case AST_CONTROL_BUSY: 00982 case AST_CONTROL_CONGESTION: 00983 case AST_CONTROL_RINGING: 00984 res = cond; 00985 break; 00986 00987 case -1: 00988 o->cursound = -1; 00989 o->nosound = 0; /* when cursound is -1 nosound must be 0 */ 00990 return 0; 00991 00992 case AST_CONTROL_VIDUPDATE: 00993 res = -1; 00994 break; 00995 00996 case AST_CONTROL_HOLD: 00997 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00998 ast_moh_start(c, data, o->mohinterpret); 00999 break; 01000 01001 case AST_CONTROL_UNHOLD: 01002 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 01003 ast_moh_stop(c); 01004 break; 01005 01006 default: 01007 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name); 01008 return -1; 01009 } 01010 01011 if (res > -1) 01012 ring(o, res); 01013 01014 return 0; 01015 }
|
|
||||||||||||||||||||
|
|
Definition at line 919 of file chan_oss.c. References ast_channel::_state, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_STATE_UP, chan_oss_pvt::boost, BOOST_SCALE, ast_frame::data, ast_frame::datalen, FRAME_SIZE, ast_frame::frametype, chan_oss_pvt::mute, chan_oss_pvt::oss_read_buf, oss_tech, chan_oss_pvt::read_f, chan_oss_pvt::readpos, ast_frame::samples, chan_oss_pvt::sounddev, ast_frame::src, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel_tech::type. 00920 { 00921 int res; 00922 struct chan_oss_pvt *o = c->tech_pvt; 00923 struct ast_frame *f = &o->read_f; 00924 00925 /* XXX can be simplified returning &ast_null_frame */ 00926 /* prepare a NULL frame in case we don't have enough data to return */ 00927 bzero(f, sizeof(struct ast_frame)); 00928 f->frametype = AST_FRAME_NULL; 00929 f->src = oss_tech.type; 00930 00931 res = read(o->sounddev, o->oss_read_buf + o->readpos, sizeof(o->oss_read_buf) - o->readpos); 00932 if (res < 0) /* audio data not ready, return a NULL frame */ 00933 return f; 00934 00935 o->readpos += res; 00936 if (o->readpos < sizeof(o->oss_read_buf)) /* not enough samples */ 00937 return f; 00938 00939 if (o->mute) 00940 return f; 00941 00942 o->readpos = AST_FRIENDLY_OFFSET; /* reset read pointer for next frame */ 00943 if (c->_state != AST_STATE_UP) /* drop data if frame is not up */ 00944 return f; 00945 /* ok we can build and deliver the frame to the caller */ 00946 f->frametype = AST_FRAME_VOICE; 00947 f->subclass = AST_FORMAT_SLINEAR; 00948 f->samples = FRAME_SIZE; 00949 f->datalen = FRAME_SIZE * 2; 00950 f->data = o->oss_read_buf + AST_FRIENDLY_OFFSET; 00951 if (o->boost != BOOST_SCALE) { /* scale and clip values */ 00952 int i, x; 00953 int16_t *p = (int16_t *) f->data; 00954 for (i = 0; i < f->samples; i++) { 00955 x = (p[i] * o->boost) / BOOST_SCALE; 00956 if (x > 32767) 00957 x = 32767; 00958 else if (x < -32768) 00959 x = -32768; 00960 p[i] = x; 00961 } 00962 } 00963 00964 f->offset = AST_FRIENDLY_OFFSET; 00965 return f; 00966 }
|
|
||||||||||||||||||||
|
Definition at line 1065 of file chan_oss.c. References AST_APP_ARG, AST_CAUSE_BUSY, AST_DECLARE_APP_ARGS, AST_FORMAT_SLINEAR, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STATE_DOWN, ast_strdupa, find_desc(), LOG_NOTICE, LOG_WARNING, name, oss_new(), chan_oss_pvt::owner, and parse(). 01066 { 01067 struct ast_channel *c; 01068 struct chan_oss_pvt *o; 01069 AST_DECLARE_APP_ARGS(args, 01070 AST_APP_ARG(name); 01071 AST_APP_ARG(flags); 01072 ); 01073 char *parse = ast_strdupa(data); 01074 01075 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 01076 o = find_desc(args.name); 01077 01078 ast_log(LOG_WARNING, "oss_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data); 01079 if (o == NULL) { 01080 ast_log(LOG_NOTICE, "Device %s not found\n", args.name); 01081 /* XXX we could default to 'dsp' perhaps ? */ 01082 return NULL; 01083 } 01084 if ((format & AST_FORMAT_SLINEAR) == 0) { 01085 ast_log(LOG_NOTICE, "Format 0x%x unsupported\n", format); 01086 return NULL; 01087 } 01088 if (o->owner) { 01089 ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner); 01090 *cause = AST_CAUSE_BUSY; 01091 return NULL; 01092 } 01093 c = oss_new(o, NULL, NULL, AST_STATE_DOWN); 01094 if (c == NULL) { 01095 ast_log(LOG_WARNING, "Unable to create new OSS channel\n"); 01096 return NULL; 01097 } 01098 return c; 01099 }
|
|
||||||||||||
|
Definition at line 787 of file chan_oss.c. References ast_verbose(). 00788 { 00789 /* print received messages */ 00790 ast_verbose(" << Console Received text %s >> \n", text); 00791 return 0; 00792 }
|
|
||||||||||||
|
used for data coming from the network
Definition at line 883 of file chan_oss.c. References chan_oss_pvt::cursound, ast_frame::data, ast_frame::datalen, chan_oss_pvt::nosound, chan_oss_pvt::oss_write_buf, chan_oss_pvt::oss_write_dst, soundcard_writeframe(), and ast_channel::tech_pvt. 00884 { 00885 int src; 00886 struct chan_oss_pvt *o = c->tech_pvt; 00887 00888 /* Immediately return if no sound is enabled */ 00889 if (o->nosound) 00890 return 0; 00891 /* Stop any currently playing sound */ 00892 o->cursound = -1; 00893 /* 00894 * we could receive a block which is not a multiple of our 00895 * FRAME_SIZE, so buffer it locally and write to the device 00896 * in FRAME_SIZE chunks. 00897 * Keep the residue stored for future use. 00898 */ 00899 src = 0; /* read position into f->data */ 00900 while (src < f->datalen) { 00901 /* Compute spare room in the buffer */ 00902 int l = sizeof(o->oss_write_buf) - o->oss_write_dst; 00903 00904 if (f->datalen - src >= l) { /* enough to fill a frame */ 00905 memcpy(o->oss_write_buf + o->oss_write_dst, f->data + src, l); 00906 soundcard_writeframe(o, (short *) o->oss_write_buf); 00907 src += l; 00908 o->oss_write_dst = 0; 00909 } else { /* copy residue */ 00910 l = f->datalen - src; 00911 memcpy(o->oss_write_buf + o->oss_write_dst, f->data + src, l); 00912 src += l; /* but really, we are done */ 00913 o->oss_write_dst += l; 00914 } 00915 } 00916 return 0; 00917 }
|
|
||||||||||||
|
Play ringtone 'x' on device 'o'.
Definition at line 795 of file chan_oss.c. References chan_oss_pvt::sndcmd. Referenced by ast_extension_state2(), ind_load_module(), oss_answer(), oss_call(), oss_hangup(), and oss_indicate(). 00796 { 00797 write(o->sndcmd[1], &x, sizeof(x)); 00798 }
|
|
|
Handler for 'sound writable' events from the sound thread. Builds a frame from the high level description of the sounds, and passes it to the audio device. The actual sound is made of 1 or more sequences of sound samples (s->datalen, repeated to make s->samplen samples) followed by s->silencelen samples of silence. The position in the sequence is stored in o->sampsent, which goes between 0 .. s->samplen+s->silencelen. In case we fail to write a frame, don't update o->sampsent. Definition at line 551 of file chan_oss.c. References ast_log(), chan_oss_pvt::cursound, FRAME_SIZE, LOG_WARNING, MIN, s, chan_oss_pvt::sampsent, and sounds. 00552 { 00553 short myframe[FRAME_SIZE]; 00554 int ofs, l, start; 00555 int l_sampsent = o->sampsent; 00556 struct sound *s; 00557 00558 if (o->cursound < 0) /* no sound to send */ 00559 return; 00560 00561 s = &sounds[o->cursound]; 00562 00563 for (ofs = 0; ofs < FRAME_SIZE; ofs += l) { 00564 l = s->samplen - l_sampsent; /* # of available samples */ 00565 if (l > 0) { 00566 start = l_sampsent % s->datalen; /* source offset */ 00567 l = MIN(l, FRAME_SIZE - ofs); /* don't overflow the frame */ 00568 l = MIN(l, s->datalen - start); /* don't overflow the source */ 00569 bcopy(s->data + start, myframe + ofs, l * 2); 00570 if (0) 00571 ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs); 00572 l_sampsent += l; 00573 } else { /* end of samples, maybe some silence */ 00574 static const short silence[FRAME_SIZE] = { 0, }; 00575 00576 l += s->silencelen; 00577 if (l > 0) { 00578 l = MIN(l, FRAME_SIZE - ofs); 00579 bcopy(silence, myframe + ofs, l * 2); 00580 l_sampsent += l; 00581 } else { /* silence is over, restart sound if loop */ 00582 if (s->repeat == 0) { /* last block */ 00583 o->cursound = -1; 00584 o->nosound = 0; /* allow audio data */ 00585 if (ofs < FRAME_SIZE) /* pad with silence */ 00586 bcopy(silence, myframe + ofs, (FRAME_SIZE - ofs) * 2); 00587 } 00588 l_sampsent = 0; 00589 } 00590 } 00591 } 00592 l = soundcard_writeframe(o, myframe); 00593 if (l > 0) 00594 o->sampsent = l_sampsent; /* update status */ 00595 }
|
|
||||||||||||
|
reset and close the device if opened, then open and initialize it in the desired mode, trigger reads and writes so we can start using it. Definition at line 674 of file chan_oss.c. References ast_log(), ast_verbose(), DEFAULT_SAMPLE_RATE, chan_oss_pvt::device, chan_oss_pvt::duplex, ast_channel::fds, fmt, chan_oss_pvt::frags, chan_oss_pvt::lastopen, LOG_WARNING, O_CLOSE, option_verbose, chan_oss_pvt::owner, chan_oss_pvt::sounddev, VERBOSE_PREFIX_2, WARN_frag, WARN_speed, and chan_oss_pvt::warned. Referenced by console_hangup(), oss_hangup(), oss_new(), sound_thread(), and soundcard_writeframe(). 00675 { 00676 int fmt, desired, res, fd; 00677 00678 if (o->sounddev >= 0) { 00679 ioctl(o->sounddev, SNDCTL_DSP_RESET, 0); 00680 close(o->sounddev); 00681 o->duplex = M_UNSET; 00682 o->sounddev = -1; 00683 } 00684 if (mode == O_CLOSE) /* we are done */ 00685 return 0; 00686 if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000) 00687 return -1; /* don't open too often */ 00688 o->lastopen = ast_tvnow(); 00689 fd = o->sounddev = open(o->device, mode | O_NONBLOCK); 00690 if (fd < 0) { 00691 ast_log(LOG_WARNING, "Unable to re-open DSP device %s: %s\n", o->device, strerror(errno)); 00692 return -1; 00693 } 00694 if (o->owner) 00695 o->owner->fds[0] = fd; 00696 00697 #if __BYTE_ORDER == __LITTLE_ENDIAN 00698 fmt = AFMT_S16_LE; 00699 #else 00700 fmt = AFMT_S16_BE; 00701 #endif 00702 res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); 00703 if (res < 0) { 00704 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n"); 00705 return -1; 00706 } 00707 switch (mode) { 00708 case O_RDWR: 00709 res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); 00710 /* Check to see if duplex set (FreeBSD Bug) */ 00711 res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt); 00712 if (res == 0 && (fmt & DSP_CAP_DUPLEX)) { 00713 if (option_verbose > 1) 00714 ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n"); 00715 o->duplex = M_FULL; 00716 }; 00717 break; 00718 00719 case O_WRONLY: 00720 o->duplex = M_WRITE; 00721 break; 00722 00723 case O_RDONLY: 00724 o->duplex = M_READ; 00725 break; 00726 } 00727 00728 fmt = 0; 00729 res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt); 00730 if (res < 0) { 00731 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00732 return -1; 00733 } 00734 fmt = desired = DEFAULT_SAMPLE_RATE; /* 8000 Hz desired */ 00735 res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt); 00736 00737 if (res < 0) { 00738 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00739 return -1; 00740 } 00741 if (fmt != desired) { 00742 if (!(o->warned & WARN_speed)) { 00743 ast_log(LOG_WARNING, 00744 "Requested %d Hz, got %d Hz -- sound may be choppy\n", 00745 desired, fmt); 00746 o->warned |= WARN_speed; 00747 } 00748 } 00749 /* 00750 * on Freebsd, SETFRAGMENT does not work very well on some cards. 00751 * Default to use 256 bytes, let the user override 00752 */ 00753 if (o->frags) { 00754 fmt = o->frags; 00755 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt); 00756 if (res < 0) { 00757 if (!(o->warned & WARN_frag)) { 00758 ast_log(LOG_WARNING, 00759 "Unable to set fragment size -- sound may be choppy\n"); 00760 o->warned |= WARN_frag; 00761 } 00762 } 00763 } 00764 /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */ 00765 res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT; 00766 res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res); 00767 /* it may fail if we are in half duplex, never mind */ 00768 return 0; 00769 }
|
|
|
Definition at line 597 of file chan_oss.c. References ast_log(), ast_select(), chan_oss_pvt::cursound, DEFAULT_SAMPLE_RATE, FRAME_SIZE, sound::ind, LOG_WARNING, MAX, O_CLOSE, chan_oss_pvt::owner, setformat(), chan_oss_pvt::sndcmd, chan_oss_pvt::sounddev, and sounds. 00598 { 00599 char ign[4096]; 00600 struct chan_oss_pvt *o = (struct chan_oss_pvt *) arg; 00601 00602 /* 00603 * Just in case, kick the driver by trying to read from it. 00604 * Ignore errors - this read is almost guaranteed to fail. 00605 */ 00606 read(o->sounddev, ign, sizeof(ign)); 00607 for (;;) { 00608 fd_set rfds, wfds; 00609 int maxfd, res; 00610 struct timeval *to = NULL, t; 00611 00612 FD_ZERO(&rfds); 00613 FD_ZERO(&wfds); 00614 FD_SET(o->sndcmd[0], &rfds); 00615 maxfd = o->sndcmd[0]; /* pipe from the main process */ 00616 if (o->cursound > -1 && o->sounddev < 0) 00617 setformat(o, O_RDWR); /* need the channel, try to reopen */ 00618 else if (o->cursound == -1 && o->owner == NULL) 00619 setformat(o, O_CLOSE); /* can close */ 00620 if (o->sounddev > -1) { 00621 if (!o->owner) { /* no one owns the audio, so we must drain it */ 00622 FD_SET(o->sounddev, &rfds); 00623 maxfd = MAX(o->sounddev, maxfd); 00624 } 00625 if (o->cursound > -1) { 00626 /* 00627 * We would like to use select here, but the device 00628 * is always writable, so this would become busy wait. 00629 * So we rather set a timeout to 1/2 of the frame size. 00630 */ 00631 t.tv_sec = 0; 00632 t.tv_usec = (1000000 * FRAME_SIZE) / (5 * DEFAULT_SAMPLE_RATE); 00633 to = &t; 00634 } 00635 } 00636 /* ast_select emulates linux behaviour in terms of timeout handling */ 00637 res = ast_select(maxfd + 1, &rfds, &wfds, NULL, to); 00638 if (res < 0) { 00639 ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); 00640 sleep(1); 00641 continue; 00642 } 00643 if (FD_ISSET(o->sndcmd[0], &rfds)) { 00644 /* read which sound to play from the pipe */ 00645 int i, what = -1; 00646 00647 read(o->sndcmd[0], &what, sizeof(what)); 00648 for (i = 0; sounds[i].ind != -1; i++) { 00649 if (sounds[i].ind == what) { 00650 o->cursound = i; 00651 o->sampsent = 0; 00652 o->nosound = 1; /* block audio from pbx */ 00653 break; 00654 } 00655 } 00656 if (sounds[i].ind == -1) 00657 ast_log(LOG_WARNING, "invalid sound index: %d\n", what); 00658 } 00659 if (o->sounddev > -1) { 00660 if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */ 00661 read(o->sounddev, ign, sizeof(ign)); 00662 if (to != NULL) /* maybe it is possible to write */ 00663 send_sound(o); 00664 } 00665 } 00666 return NULL; /* Never reached */ 00667 }
|
|
||||||||||||
|
Write an exactly FRAME_SIZE sized frame Definition at line 516 of file chan_oss.c. References ast_log(), FRAME_SIZE, LOG_WARNING, chan_oss_pvt::queuesize, setformat(), chan_oss_pvt::sounddev, used_blocks(), and chan_oss_pvt::w_errors. Referenced by oss_write(). 00517 { 00518 int res; 00519 00520 if (o->sounddev < 0) 00521 setformat(o, O_RDWR); 00522 if (o->sounddev < 0) 00523 return 0; /* not fatal */ 00524 /* 00525 * Nothing complex to manage the audio device queue. 00526 * If the buffer is full just drop the extra, otherwise write. 00527 * XXX in some cases it might be useful to write anyways after 00528 * a number of failures, to restart the output chain. 00529 */ 00530 res = used_blocks(o); 00531 if (res > o->queuesize) { /* no room to write a block */ 00532 if (o->w_errors++ == 0 && (oss_debug & 0x4)) 00533 ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors); 00534 return 0; 00535 } 00536 o->w_errors = 0; 00537 return write(o->sounddev, (void *)data, FRAME_SIZE * 2); 00538 }
|
|
||||||||||||
|
store the boost factor
Definition at line 1409 of file chan_oss.c. References ast_log(), chan_oss_pvt::boost, BOOST_MAX, BOOST_SCALE, and LOG_WARNING. Referenced by do_boost(), and store_config(). 01410 { 01411 double boost = 0; 01412 if (sscanf(s, "%lf", &boost) != 1) { 01413 ast_log(LOG_WARNING, "invalid boost <%s>\n", s); 01414 return; 01415 } 01416 if (boost < -BOOST_MAX) { 01417 ast_log(LOG_WARNING, "boost %s too small, using %d\n", s, -BOOST_MAX); 01418 boost = -BOOST_MAX; 01419 } else if (boost > BOOST_MAX) { 01420 ast_log(LOG_WARNING, "boost %s too large, using %d\n", s, BOOST_MAX); 01421 boost = BOOST_MAX; 01422 } 01423 boost = exp(log(10) * boost / 20) * BOOST_SCALE; 01424 o->boost = boost; 01425 ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost); 01426 }
|
|
||||||||||||
|
store the callerid components Definition at line 1485 of file chan_oss.c. References ast_callerid_split(), chan_oss_pvt::cid_name, and chan_oss_pvt::cid_num. Referenced by store_config(). 01486 { 01487 ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num)); 01488 }
|
|
||||||||||||
|
grab fields from the config file, init the descriptor and open the device. Definition at line 1493 of file chan_oss.c. References ast_calloc, ast_jb_read_conf(), ast_strdup, ast_variable_browse(), chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, chan_oss_pvt::ctx, chan_oss_pvt::device, chan_oss_pvt::ext, chan_oss_pvt::frags, global_jbconf, chan_oss_pvt::language, chan_oss_pvt::lastopen, M_BOOL, M_END, M_F, M_START, M_STR, M_UINT, chan_oss_pvt::mohinterpret, ast_variable::name, chan_oss_pvt::name, ast_variable::next, oss_default, chan_oss_pvt::overridecontext, chan_oss_pvt::queuesize, store_boost(), store_callerid(), store_mixer(), and ast_variable::value. Referenced by load_module(). 01494 { 01495 struct ast_variable *v; 01496 struct chan_oss_pvt *o; 01497 01498 if (ctg == NULL) { 01499 o = &oss_default; 01500 ctg = "general"; 01501 } else { 01502 if (!(o = ast_calloc(1, sizeof(*o)))) 01503 return NULL; 01504 *o = oss_default; 01505 /* "general" is also the default thing */ 01506 if (strcmp(ctg, "general") == 0) { 01507 o->name = ast_strdup("dsp"); 01508 oss_active = o->name; 01509 goto openit; 01510 } 01511 o->name = ast_strdup(ctg); 01512 } 01513 01514 strcpy(o->mohinterpret, "default"); 01515 01516 o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */ 01517 /* fill other fields from configuration */ 01518 for (v = ast_variable_browse(cfg, ctg); v; v = v->next) { 01519 M_START(v->name, v->value); 01520 01521 /* handle jb conf */ 01522 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 01523 continue; 01524 01525 M_BOOL("autoanswer", o->autoanswer) 01526 M_BOOL("autohangup", o->autohangup) 01527 M_BOOL("overridecontext", o->overridecontext) 01528 M_STR("device", o->device) 01529 M_UINT("frags", o->frags) 01530 M_UINT("debug", oss_debug) 01531 M_UINT("queuesize", o->queuesize) 01532 M_STR("context", o->ctx) 01533 M_STR("language", o->language) 01534 M_STR("mohinterpret", o->mohinterpret) 01535 M_STR("extension", o->ext) 01536 M_F("mixer", store_mixer(o, v->value)) 01537 M_F("callerid", store_callerid(o, v->value)) 01538 M_F("boost", store_boost(o, v->value)) 01539 01540 M_END(/* */); 01541 } 01542 if (ast_strlen_zero(o->device)) 01543 ast_copy_string(o->device, DEV_DSP, sizeof(o->device)); 01544 if (o->mixer_cmd) { 01545 char *cmd; 01546 01547 asprintf(&cmd, "mixer %s", o->mixer_cmd); 01548 ast_log(LOG_WARNING, "running [%s]\n", cmd); 01549 system(cmd); 01550 free(cmd); 01551 } 01552 if (o == &oss_default) /* we are done with the default */ 01553 return NULL; 01554 01555 openit: 01556 #if TRYOPEN 01557 if (setformat(o, O_RDWR) < 0) { /* open device */ 01558 if (option_verbose > 0) { 01559 ast_verbose(VERBOSE_PREFIX_2 "Device %s not detected\n", ctg); 01560 ast_verbose(VERBOSE_PREFIX_2 "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n"); 01561 } 01562 goto error; 01563 } 01564 if (o->duplex != M_FULL) 01565 ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n"); 01566 #endif /* TRYOPEN */ 01567 if (pipe(o->sndcmd) != 0) { 01568 ast_log(LOG_ERROR, "Unable to create pipe\n"); 01569 goto error; 01570 } 01571 ast_pthread_create_background(&o->sthread, NULL, sound_thread, o); 01572 /* link into list of devices */ 01573 if (o != &oss_default) { 01574 o->next = oss_default.next; 01575 oss_default.next = o; 01576 } 01577 return o; 01578 01579 error: 01580 if (o != &oss_default) 01581 free(o); 01582 return NULL; 01583 }
|
|
||||||||||||
|
store the mixer argument from the config file, filtering possibly invalid or dangerous values (the string is used as argument for system("mixer %s") Definition at line 1466 of file chan_oss.c. References ast_log(), and LOG_WARNING. Referenced by store_config(). 01467 { 01468 int i; 01469 01470 for (i = 0; i < strlen(s); i++) { 01471 if (!isalnum(s[i]) && index(" \t-/", s[i]) == NULL) { 01472 ast_log(LOG_WARNING, "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s); 01473 return; 01474 } 01475 } 01476 if (o->mixer_cmd) 01477 free(o->mixer_cmd); 01478 o->mixer_cmd = ast_strdup(s); 01479 ast_log(LOG_WARNING, "setting mixer %s\n", s); 01480 }
|
|
|
Definition at line 1623 of file chan_oss.c. References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_oss, chan_oss_pvt::next, oss_default, oss_tech, chan_oss_pvt::owner, chan_oss_pvt::sndcmd, and chan_oss_pvt::sounddev. 01624 { 01625 struct chan_oss_pvt *o; 01626 01627 ast_channel_unregister(&oss_tech); 01628 ast_cli_unregister_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry)); 01629 01630 for (o = oss_default.next; o; o = o->next) { 01631 close(o->sounddev); 01632 if (o->sndcmd[0] > 0) { 01633 close(o->sndcmd[0]); 01634 close(o->sndcmd[1]); 01635 } 01636 if (o->owner) 01637 ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); 01638 if (o->owner) /* XXX how ??? */ 01639 return -1; 01640 /* XXX what about the thread ? */ 01641 /* XXX what about the memory allocated ? */ 01642 } 01643 return 0; 01644 }
|
|
|
Returns the number of blocks used in the audio output channel.
Definition at line 494 of file chan_oss.c. References ast_log(), LOG_WARNING, chan_oss_pvt::sounddev, chan_oss_pvt::total_blocks, WARN_used_blocks, and chan_oss_pvt::warned. Referenced by soundcard_writeframe(). 00495 { 00496 struct audio_buf_info info; 00497 00498 if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) { 00499 if (!(o->warned & WARN_used_blocks)) { 00500 ast_log(LOG_WARNING, "Error reading output space\n"); 00501 o->warned |= WARN_used_blocks; 00502 } 00503 return 1; 00504 } 00505 00506 if (o->total_blocks == 0) { 00507 if (0) /* debugging */ 00508 ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments); 00509 o->total_blocks = info.fragments; 00510 } 00511 00512 return o->total_blocks - info.fragments; 00513 }
|
|
|
Initial value: "Usage: console active [device]\n" " If used without a parameter, displays which device is the current\n" "console. If a device is specified, the console sound device is changed to\n" "the device specified.\n" Definition at line 1400 of file chan_oss.c. |
|
|
Definition at line 1439 of file chan_oss.c. Referenced by load_module(), and unload_module(). |
|
|
Definition at line 285 of file chan_oss.c. |
|
|
Global jitterbuffer configuration - by default, jb is disabled Definition at line 87 of file chan_oss.c. |
|
|
Definition at line 94 of file chan_oss.c. |
|
|
the active device Definition at line 402 of file chan_oss.c. |
|
|
Definition at line 287 of file chan_oss.c. |
|
|
Definition at line 387 of file chan_oss.c. Referenced by console_active(), find_desc(), store_config(), and unload_module(). |
|
|
Definition at line 420 of file chan_oss.c. Referenced by load_module(), oss_new(), oss_read(), and unload_module(). |
|
|
Definition at line 304 of file chan_oss.c. |
|
|
Definition at line 418 of file chan_oss.c. |
|
|
Initial value: "Usage: console transfer <extension>[@context]\n" " Transfers the currently connected call to the given extension (and\n" "context if specified)\n" Definition at line 1373 of file chan_oss.c. |