📄 chan_oss.c
字号:
return RESULT_SHOWUSAGE; return __console_mute_unmute(1);}static int console_mute(int fd, int argc, char *argv[]){ if (argc != 2) return RESULT_SHOWUSAGE; return __console_mute_unmute(1);}static char mute_usage[] = "Usage: console mute\nMutes the microphone\n";static int console_unmute_deprecated(int fd, int argc, char *argv[]){ if (argc != 1) return RESULT_SHOWUSAGE; return __console_mute_unmute(0);}static int console_unmute(int fd, int argc, char *argv[]){ if (argc != 2) return RESULT_SHOWUSAGE; return __console_mute_unmute(0);}static char unmute_usage[] = "Usage: console unmute\nUnmutes the microphone\n";static int console_transfer_deprecated(int fd, int argc, char *argv[]){ struct chan_oss_pvt *o = find_desc(oss_active); struct ast_channel *b = NULL; char *tmp, *ext, *ctx; if (argc != 2) return RESULT_SHOWUSAGE; if (o == NULL) return RESULT_FAILURE; if (o->owner ==NULL || (b = ast_bridged_channel(o->owner)) == NULL) { ast_cli(fd, "There is no call to transfer\n"); return RESULT_SUCCESS; } tmp = ast_ext_ctx(argv[1], &ext, &ctx); if (ctx == NULL) /* supply default context if needed */ ctx = o->owner->context; if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num)) ast_cli(fd, "No such extension exists\n"); else { ast_cli(fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx); if (ast_async_goto(b, ctx, ext, 1)) ast_cli(fd, "Failed to transfer :(\n"); } if (tmp) free(tmp); return RESULT_SUCCESS;}static int console_transfer(int fd, int argc, char *argv[]){ struct chan_oss_pvt *o = find_desc(oss_active); struct ast_channel *b = NULL; char *tmp, *ext, *ctx; if (argc != 3) return RESULT_SHOWUSAGE; if (o == NULL) return RESULT_FAILURE; if (o->owner == NULL || (b = ast_bridged_channel(o->owner)) == NULL) { ast_cli(fd, "There is no call to transfer\n"); return RESULT_SUCCESS; } tmp = ast_ext_ctx(argv[2], &ext, &ctx); if (ctx == NULL) /* supply default context if needed */ ctx = o->owner->context; if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num)) ast_cli(fd, "No such extension exists\n"); else { ast_cli(fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx); if (ast_async_goto(b, ctx, ext, 1)) ast_cli(fd, "Failed to transfer :(\n"); } if (tmp) free(tmp); return RESULT_SUCCESS;}static char transfer_usage[] = "Usage: console transfer <extension>[@context]\n" " Transfers the currently connected call to the given extension (and\n" "context if specified)\n";static int console_active_deprecated(int fd, int argc, char *argv[]){ if (argc == 1) ast_cli(fd, "active console is [%s]\n", oss_active); else if (argc != 2) return RESULT_SHOWUSAGE; else { struct chan_oss_pvt *o; if (strcmp(argv[1], "show") == 0) { for (o = oss_default.next; o; o = o->next) ast_cli(fd, "device [%s] exists\n", o->name); return RESULT_SUCCESS; } o = find_desc(argv[1]); if (o == NULL) ast_cli(fd, "No device [%s] exists\n", argv[1]); else oss_active = o->name; } return RESULT_SUCCESS;}static int console_active(int fd, int argc, char *argv[]){ if (argc == 2) ast_cli(fd, "active console is [%s]\n", oss_active); else if (argc != 3) return RESULT_SHOWUSAGE; else { struct chan_oss_pvt *o; if (strcmp(argv[2], "show") == 0) { for (o = oss_default.next; o; o = o->next) ast_cli(fd, "device [%s] exists\n", o->name); return RESULT_SUCCESS; } o = find_desc(argv[2]); if (o == NULL) ast_cli(fd, "No device [%s] exists\n", argv[2]); else oss_active = o->name; } return RESULT_SUCCESS;}static char active_usage[] = "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";/* * store the boost factor */static void store_boost(struct chan_oss_pvt *o, char *s){ double boost = 0; if (sscanf(s, "%lf", &boost) != 1) { ast_log(LOG_WARNING, "invalid boost <%s>\n", s); return; } if (boost < -BOOST_MAX) { ast_log(LOG_WARNING, "boost %s too small, using %d\n", s, -BOOST_MAX); boost = -BOOST_MAX; } else if (boost > BOOST_MAX) { ast_log(LOG_WARNING, "boost %s too large, using %d\n", s, BOOST_MAX); boost = BOOST_MAX; } boost = exp(log(10) * boost / 20) * BOOST_SCALE; o->boost = boost; ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost);}static int do_boost(int fd, int argc, char *argv[]){ struct chan_oss_pvt *o = find_desc(oss_active); if (argc == 2) ast_cli(fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE))); else if (argc == 3) store_boost(o, argv[2]); return RESULT_SUCCESS;}static struct ast_cli_entry cli_oss_answer_deprecated = { { "answer", NULL }, console_answer_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_hangup_deprecated = { { "hangup", NULL }, console_hangup_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_flash_deprecated = { { "flash", NULL }, console_flash_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_dial_deprecated = { { "dial", NULL }, console_dial_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_mute_deprecated = { { "mute", NULL }, console_mute_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_unmute_deprecated = { { "unmute", NULL }, console_unmute_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_transfer_deprecated = { { "transfer", NULL }, console_transfer_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_send_text_deprecated = { { "send", "text", NULL }, console_sendtext_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss_autoanswer_deprecated = { { "autoanswer", NULL }, console_autoanswer_deprecated, NULL, NULL, autoanswer_complete_deprecated };static struct ast_cli_entry cli_oss_boost_deprecated = { { "oss", "boost", NULL }, do_boost, NULL, NULL };static struct ast_cli_entry cli_oss_active_deprecated = { { "console", NULL }, console_active_deprecated, NULL, NULL };static struct ast_cli_entry cli_oss[] = { { { "console", "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage, NULL, &cli_oss_answer_deprecated }, { { "console", "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage, NULL, &cli_oss_hangup_deprecated }, { { "console", "flash", NULL }, console_flash, "Flash a call on the console", flash_usage, NULL, &cli_oss_flash_deprecated }, { { "console", "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage, NULL, &cli_oss_dial_deprecated }, { { "console", "mute", NULL }, console_mute, "Disable mic input", mute_usage, NULL, &cli_oss_mute_deprecated }, { { "console", "unmute", NULL }, console_unmute, "Enable mic input", unmute_usage, NULL, &cli_oss_unmute_deprecated }, { { "console", "transfer", NULL }, console_transfer, "Transfer a call to a different extension", transfer_usage, NULL, &cli_oss_transfer_deprecated }, { { "console", "send", "text", NULL }, console_sendtext, "Send text to the remote device", sendtext_usage, NULL, &cli_oss_send_text_deprecated }, { { "console", "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete, &cli_oss_autoanswer_deprecated }, { { "console", "boost", NULL }, do_boost, "Sets/displays mic boost in dB", NULL, NULL, &cli_oss_boost_deprecated }, { { "console", "active", NULL }, console_active, "Sets/displays active console", active_usage, NULL, &cli_oss_active_deprecated },};/* * store the mixer argument from the config file, filtering possibly * invalid or dangerous values (the string is used as argument for * system("mixer %s") */static void store_mixer(struct chan_oss_pvt *o, char *s){ int i; for (i = 0; i < strlen(s); i++) { if (!isalnum(s[i]) && index(" \t-/", s[i]) == NULL) { ast_log(LOG_WARNING, "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s); return; } } if (o->mixer_cmd) free(o->mixer_cmd); o->mixer_cmd = ast_strdup(s); ast_log(LOG_WARNING, "setting mixer %s\n", s);}/* * store the callerid components */static void store_callerid(struct chan_oss_pvt *o, char *s){ ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));}/* * grab fields from the config file, init the descriptor and open the device. */static struct chan_oss_pvt *store_config(struct ast_config *cfg, char *ctg){ struct ast_variable *v; struct chan_oss_pvt *o; if (ctg == NULL) { o = &oss_default; ctg = "general"; } else { if (!(o = ast_calloc(1, sizeof(*o)))) return NULL; *o = oss_default; /* "general" is also the default thing */ if (strcmp(ctg, "general") == 0) { o->name = ast_strdup("dsp"); oss_active = o->name; goto openit; } o->name = ast_strdup(ctg); } strcpy(o->mohinterpret, "default"); o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */ /* fill other fields from configuration */ for (v = ast_variable_browse(cfg, ctg); v; v = v->next) { M_START(v->name, v->value); /* handle jb conf */ if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) continue; M_BOOL("autoanswer", o->autoanswer) M_BOOL("autohangup", o->autohangup) M_BOOL("overridecontext", o->overridecontext) M_STR("device", o->device) M_UINT("frags", o->frags) M_UINT("debug", oss_debug) M_UINT("queuesize", o->queuesize) M_STR("context", o->ctx) M_STR("language", o->language) M_STR("mohinterpret", o->mohinterpret) M_STR("extension", o->ext) M_F("mixer", store_mixer(o, v->value)) M_F("callerid", store_callerid(o, v->value)) M_F("boost", store_boost(o, v->value)) M_END(; ); } if (ast_strlen_zero(o->device)) ast_copy_string(o->device, DEV_DSP, sizeof(o->device)); if (o->mixer_cmd) { char *cmd; asprintf(&cmd, "mixer %s", o->mixer_cmd); ast_log(LOG_WARNING, "running [%s]\n", cmd); system(cmd); free(cmd); } if (o == &oss_default) /* we are done with the default */ return NULL; openit:#if TRYOPEN if (setformat(o, O_RDWR) < 0) { /* open device */ if (option_verbose > 0) { ast_verbose(VERBOSE_PREFIX_2 "Device %s not detected\n", ctg); ast_verbose(VERBOSE_PREFIX_2 "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n"); } goto error; } if (o->duplex != M_FULL) ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n");#endif /* TRYOPEN */ if (pipe(o->sndcmd) != 0) { ast_log(LOG_ERROR, "Unable to create pipe\n"); goto error; } ast_pthread_create_background(&o->sthread, NULL, sound_thread, o); /* link into list of devices */ if (o != &oss_default) { o->next = oss_default.next; oss_default.next = o; } return o; error: if (o != &oss_default) free(o); return NULL;}static int load_module(void){ struct ast_config *cfg = NULL; char *ctg = NULL; /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); /* load config file */ if (!(cfg = ast_config_load(config))) { ast_log(LOG_NOTICE, "Unable to load config %s\n", config); return AST_MODULE_LOAD_DECLINE; } do { store_config(cfg, ctg); } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL); ast_config_destroy(cfg); if (find_desc(oss_active) == NULL) { ast_log(LOG_NOTICE, "Device %s not found\n", oss_active); /* XXX we could default to 'dsp' perhaps ? */ /* XXX should cleanup allocated memory etc. */ return AST_MODULE_LOAD_FAILURE; } if (ast_channel_register(&oss_tech)) { ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n"); return AST_MODULE_LOAD_FAILURE; } ast_cli_register_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry)); return AST_MODULE_LOAD_SUCCESS;}static int unload_module(void){ struct chan_oss_pvt *o; ast_channel_unregister(&oss_tech); ast_cli_unregister_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry)); for (o = oss_default.next; o; o = o->next) { close(o->sounddev); if (o->sndcmd[0] > 0) { close(o->sndcmd[0]); close(o->sndcmd[1]); } if (o->owner) ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); if (o->owner) /* XXX how ??? */ return -1; /* XXX what about the thread ? */ /* XXX what about the memory allocated ? */ } return 0;}AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "OSS Console Channel Driver");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -