--- app_dial.orig 2007-01-23 11:14:44.000000000 -0700 +++ app_dial.c 2007-01-23 13:42:34.000000000 -0700 @@ -215,6 +215,7 @@ enum { OPT_CALLEE_MONITOR = (1 << 21), OPT_CALLER_MONITOR = (1 << 22), OPT_GOTO = (1 << 23), + OPT_PLAYFILE = (1 << 24), } dial_exec_option_flags; #define DIAL_STILLGOING (1 << 30) @@ -229,6 +230,7 @@ enum { OPT_ARG_CALLEE_MACRO, OPT_ARG_PRIVACY, OPT_ARG_DURATION_STOP, + OPT_ARG_PLAYFILE, /* note: this entry _MUST_ be the last one in the enum */ OPT_ARG_ARRAY_SIZE, } dial_exec_option_args; @@ -258,6 +260,7 @@ AST_APP_OPTIONS(dial_exec_options, { AST_APP_OPTION('T', OPT_CALLER_TRANSFER), AST_APP_OPTION('w', OPT_CALLEE_MONITOR), AST_APP_OPTION('W', OPT_CALLER_MONITOR), + AST_APP_OPTION_ARG('F', OPT_PLAYFILE, OPT_ARG_PLAYFILE), }); /* We define a custom "local user" structure because we @@ -390,7 +393,7 @@ static struct ast_channel *wait_for_answ char *context = NULL; char cidname[AST_MAX_EXTENSION]; - single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK)); + single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_PLAYFILE)); if (single) { /* Turn off hold music, etc */ @@ -589,7 +592,7 @@ static struct ast_channel *wait_for_answ case AST_CONTROL_RINGING: if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name); - if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) { + if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK) && !ast_test_flag(outgoing, OPT_PLAYFILE)) { ast_indicate(in, AST_CONTROL_RINGING); (*sentringing)++; } @@ -626,7 +629,7 @@ static struct ast_channel *wait_for_answ /* Ignore going off hook and flash */ break; case -1: - if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) { + if (!ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK|OPT_PLAYFILE)) { if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name); ast_indicate(in, -1); @@ -637,15 +640,15 @@ static struct ast_channel *wait_for_answ ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass); } } else if (single && (f->frametype == AST_FRAME_VOICE) && - !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK))) { + !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK|OPT_PLAYFILE))) { if (ast_write(in, f)) ast_log(LOG_DEBUG, "Unable to forward frame\n"); } else if (single && (f->frametype == AST_FRAME_IMAGE) && - !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK))) { + !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK|OPT_PLAYFILE))) { if (ast_write(in, f)) ast_log(LOG_DEBUG, "Unable to forward image\n"); } else if (single && (f->frametype == AST_FRAME_TEXT) && - !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK))) { + !(ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK|OPT_PLAYFILE))) { if (ast_write(in, f)) ast_log(LOG_DEBUG, "Unable to text\n"); } else if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) @@ -761,12 +764,16 @@ static int dial_exec_full(struct ast_cha char *var; char status[256]; int play_to_caller=0,play_to_callee=0; - int sentringing=0, moh=0; + int sentringing=0, moh=0, playfile=0; char *outbound_group = NULL; char *macro_result = NULL, *macro_transfer_dest = NULL; int digit = 0, result = 0; time_t start_time, answer_time, end_time; struct ast_app *app = NULL; + struct ast_filestream *fs; + long sample_offset = 0; + long max_length = 0; + int pfres; char *parse; AST_DECLARE_APP_ARGS(args, @@ -1037,7 +1044,7 @@ static int dial_exec_full(struct ast_cha OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | - OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID); + OPT_RINGBACK | OPT_MUSICBACK | OPT_PLAYFILE | OPT_FORCECLID); ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML); } ast_copy_string(numsubst, number, sizeof(numsubst)); @@ -1202,7 +1209,18 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(outgoing, OPT_RINGBACK)) { ast_indicate(chan, AST_CONTROL_RINGING); sentringing++; - } + } else if (ast_test_flag(outgoing, OPT_PLAYFILE)) { + playfile=1; + ast_indicate(chan, AST_CONTROL_PROGRESS); + ast_log(LOG_NOTICE, "(1) Playing File: %s\n", opt_args[OPT_ARG_PLAYFILE]); + fs = ast_openstream(chan, opt_args[OPT_ARG_PLAYFILE], chan->language); + ast_seekstream(fs, 0, SEEK_END); + max_length = ast_tellstream(fs); + ast_seekstream(fs, sample_offset, SEEK_SET); + pfres = ast_applystream(chan, fs); + pfres = ast_playstream(fs); + if (pfres) { ast_log(LOG_NOTICE, "200 result=%d endpos=%ld\n", pfres, sample_offset); } + } } else strcpy(status, "CHANUNAVAIL"); @@ -1266,7 +1284,14 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(&opts, OPT_RINGBACK)) { ast_indicate(chan, AST_CONTROL_RINGING); sentringing++; - } + } else if (ast_test_flag(&opts, OPT_PLAYFILE)) { + ast_indicate(chan, -1); + ast_log(LOG_NOTICE, "(2) Playing File: %s\n", opt_args[OPT_ARG_PLAYFILE]); + ast_seekstream(fs, sample_offset, SEEK_SET); + pfres = ast_applystream(chan, fs); + pfres = ast_playstream(fs); + if (pfres) { ast_log(LOG_NOTICE, "200 result=%d endpos=%ld\n", pfres, sample_offset); } + } /* Start autoservice on the other chan ?? */ res2 = ast_autoservice_start(chan); @@ -1339,7 +1364,13 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(&opts, OPT_RINGBACK)) { ast_indicate(chan, -1); sentringing=0; - } + } else if (ast_test_flag(&opts, OPT_PLAYFILE)) { + playfile=0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(1) Stoping audio stream\n"); + ast_stopstream(chan); + + } res2 = ast_autoservice_stop(chan); ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */ res=0; @@ -1359,7 +1390,12 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(&opts, OPT_RINGBACK)) { ast_indicate(chan, -1); sentringing=0; - } + } else if (ast_test_flag(&opts, OPT_PLAYFILE)) { + playfile=0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(2) Stoping audio stream\n"); + ast_stopstream(chan); + } res2 = ast_autoservice_stop(chan); ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ goto out; /* Is this right? */ @@ -1378,7 +1414,12 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(&opts, OPT_RINGBACK)) { ast_indicate(chan, -1); sentringing=0; - } + } else if (ast_test_flag(&opts, OPT_PLAYFILE)) { + playfile=0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(3) Stoping audio stream\n"); + ast_stopstream(chan); + } res2 = ast_autoservice_stop(chan); ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ goto out; /* Is this right? */ @@ -1393,7 +1434,12 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(&opts, OPT_RINGBACK)) { ast_indicate(chan, -1); sentringing=0; - } + } else if (ast_test_flag(&opts, OPT_PLAYFILE)) { + playfile=0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(4) Stoping audio stream\n"); + ast_stopstream(chan); + } res2 = ast_autoservice_stop(chan); ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ res=0; @@ -1411,7 +1457,12 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(&opts, OPT_RINGBACK)) { ast_indicate(chan, -1); sentringing=0; - } + } else if (ast_test_flag(&opts, OPT_PLAYFILE)) { + playfile=0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(5) Stoping audio stream\n"); + ast_stopstream(chan); + } res2 = ast_autoservice_stop(chan); ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */ res=0; @@ -1422,7 +1473,12 @@ static int dial_exec_full(struct ast_cha } else if (ast_test_flag(&opts, OPT_RINGBACK)) { ast_indicate(chan, -1); sentringing=0; - } + } else if (ast_test_flag(&opts, OPT_PLAYFILE)) { + playfile=0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(6) Stoping audio stream\n"); + ast_stopstream(chan); + } res2 = ast_autoservice_stop(chan); /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll just clog things up, and it's not useful information, not being tied to a CID */ @@ -1594,7 +1650,12 @@ static int dial_exec_full(struct ast_cha } else if (sentringing) { sentringing = 0; ast_indicate(chan, -1); - } + } else if (playfile) { + playfile = 0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(7) Stoping audio stream\n"); + ast_stopstream(chan); + } /* Be sure no generators are left on it */ ast_deactivate_generator(chan); /* Make sure channels are compatible */ @@ -1630,6 +1691,11 @@ out: } else if (sentringing) { sentringing = 0; ast_indicate(chan, -1); + } else if (playfile) { + playfile = 0; + sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; + ast_log(LOG_NOTICE, "(8) Stoping audio stream\n"); + ast_stopstream(chan); } hanguptree(outgoing, NULL); pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);