Hi.

I wanted to write a "popcorn" app for myself, both to learn how to script in extensions.conf, but also because it was something handy.

Along the way, I found myself doing something like:

[popcorn]
exten => s,1,Set(FUTURETIME=$[${EPOCH} + 10])
...
exten => s,n,While(${EPOCH} < ${FUTURETIME})
exten => s,n,Wait(0.01)
exten => s,n,EndWhile()
exten => s,n,Play(beep)
exten => s,n,Hangup()

and hating myself for it (my Asterisk runs on a 500MHz Geode LX).

So I decided it would be useful (in general, and educational for me in particular) to write a WaitUntil() application instead.

Well, I've done that.

I was going to file a bug and then post a "fix" to get their feature in, but the Bug guidelines seem to be pretty clear that this is not the way to go.

So, I'm posting here instead.

The example to paste into the documentation or extensions.conf is:

[popcorn]
exten => s,1,Answer()
; the amount of delay is set for English; you may need to adjust this time
; for other languages is there's no pause before the synchronizing beep.
exten => s,n,Set(FUTURETIME=$[${EPOCH} + 11])
exten => s,n,SayUnixTime(${FUTURETIME},Zulu,HNS)
exten => s,n,SayPhonetic(z)
exten => s,n,SayUnixTime(${FUTURETIME},,HNS)
exten => s,n,Playback(local)
exten => s,n,WaitUntil(${FUTURETIME})
exten => s,n,Playback(beep)
exten => s,n,Return()


I invoke it as:

exten => 712,1,Gosub(popcorn,s,1)
exten => 712,n,Hangup()

And lastly, attached is the source for app_waituntil.c.

It's fairly straightforward, and not very big.

But hopefully useful.

Oh, before I forget:  it does require the recording of one additional phrase,
either "local" or "localtime".  I've used "local" in my example above.  And
I read out the time first as GMT/UT (because I travel a lot), and then in the
timezone of my PBX...

-Philip


/*
 * Asterisk -- An open source telephony toolkit.
 *
 * Copyright (C) 2007, Redfish Solutions
 *
 * Philip Prindeville <[EMAIL PROTECTED]>
 *
 * See http://www.asterisk.org for more information about
 * the Asterisk project. Please do not directly contact
 * any of the maintainers of this project for assistance;
 * the project provides a web site, mailing lists and IRC
 * channels for your use.
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License Version 2. See the LICENSE file
 * at the top of the source tree.
 */

/*! \file
 *
 * \brief Sleep until the given epoch
 * 
 * \ingroup applications
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>

#include "asterisk.h"

ASTERISK_FILE_VERSION(__FILE__, "$Revision: 0 $")

#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/options.h"

static char *tdesc = "Generic WaitUntil() application";

static char *app = "WaitUntil";

static char *synopsis = "Wait (sleep) until the current time is the given 
epoch";

static char *descrip =
"  WaitUntil(epoch): Waits until the current time is that given. Returns\n"
"immediately if the epoch is in the past.\n";

STANDARD_LOCAL_USER;

LOCAL_USER_DECL;

static int waituntil_exec(struct ast_channel *chan, void *data)
{
        int res = 0;
        struct localuser *u;
        time_t future;
        struct timeval tv;
        ulong msec;

        if (ast_strlen_zero(data)) {
                ast_log(LOG_WARNING, "WaitUntil requires an argument(epoch)\n");
                return -1;
        }

        LOCAL_USER_ADD(u);

        if (sscanf(data, "%lu", &future) != 1) {
                ast_log(LOG_WARNING, "WaitUntil called with non-numeric 
argument\n");
                LOCAL_USER_REMOVE(u);
                return -1;
        }

        /*
         * Get the current time, and calculate the number of milliseconds
         * until then (rounding up from microseconds).
         */
        gettimeofday(&tv, NULL);

        if (future <= tv.tv_sec) {
                ast_log(LOG_NOTICE, "WaitUntil called in the past (now %lu, arg 
%lu)\n", tv.tv_sec, future);
                LOCAL_USER_REMOVE(u);
                return 0;
        }

        msec = (future - tv.tv_sec) * 1000 - ((tv.tv_usec + 500) / 1000);

        res = ast_safe_sleep(chan, msec);

        LOCAL_USER_REMOVE(u);

        return res;
}

int unload_module(void)
{
        int res;

        res = ast_unregister_application(app);

        STANDARD_HANGUP_LOCALUSERS;

        return res;
}

int load_module(void)
{
        int res;

        res = ast_register_application(app, waituntil_exec, synopsis, descrip);

        return res;
}

char *description(void)
{
        return tdesc;
}

int usecount(void)
{
        int res;
        STANDARD_USECOUNT(res);
        return res;
}

char *key()
{
        return ASTERISK_GPL_KEY;
}
_______________________________________________
--Bandwidth and Colocation Provided by http://www.api-digital.com--

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/asterisk-users

Reply via email to