Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sdk:scripts:voice-dispatcher-audio [2015/05/05 17:04] (current)
Line 1: Line 1:
 +====== SDK Script voice-dispatcher-audio.are ======
 +<code c voice-dispatcher-audio.are>​
 +/* DESC: This script implements an audio voice dispatcher
 + * Copyright (C) 2012 NetModule AG, Switzerland
 + */
 +
 +INTERVAL = 3;           /* 3 seconds */
 +NUMBER = "​+123456789"; ​ /* number to call when DI1 = on */
 +
 +template dispatcher {
 +    in1;
 +    audio;
 +
 +    int dispatcher ()
 +    {
 +        this.in1 = -1;
 +
 +        endpoints = nb_voice_endpoint_list();​
 +        if (is_array(endpoints)) {
 +            for (i = 0; i < length(endpoints);​ i++) {
 +                ep = endpoints[i];​
 +                id = struct_get(ep,​ "​id"​);​
 +                desc = struct_get(ep,​ "​desc"​);​
 +                state = struct_get(ep,​ "​state"​);​
 +
 +                nb_syslog("​%d:​ endpoint %d is in state %s (%s)", i, id, state, desc);
 +
 +                /* record first audio endpoint */
 +                if (is_void(aud) && left(desc, 6) == "​aud://"​) {
 +                    this.audio = ep;
 +                }
 +            }
 +        }
 +        if (is_void(this.audio)) {
 +            nb_syslog("​no audio endpoint found"​);​
 +            return -1;
 +        } else {
 +            nb_syslog("​using endpoint %s\n", struct_get(this.audio,​ "​desc"​));​
 +            return 0;
 +        }
 +    }
 +
 +    int checkdio () 
 +    {
 +        in1 = nb_dio_get("​in1"​);​
 +
 +        if (in1 == this.in1) {
 +            /* no state change */
 +            return -1; 
 +        } else {
 +            /* update state */
 +            nb_syslog("​updating dio state"​);​
 +            this.in1 = in1;
 +            return in1;
 +        }
 +    }
 +
 +    int handle_dio_event (int ev)
 +    {
 +        /* update endpoint first */
 +        au = nb_voice_endpoint_get(d.audio);​
 +        if (!is_struct(au)) {
 +            nb_syslog("​updating audio endpoint failed"​);​
 +            return -1;
 +        }
 +        audesc = struct_get(au,​ "​desc"​);​
 +        austate = struct_get(au,​ "​state"​);​
 +
 +        /* get list of currently active calls */
 +        calls = nb_voice_call_list();​
 +
 +        if (ev == 1) {
 +            nb_syslog("​DI1 has been closed"​);​
 +
 +            if (austate == "​available"​) {
 +                /* initiate new call */
 +                call = mkstruct("​calling",​ audesc,
 +                                "​called",​ NUMBER);
 +
 +                nb_syslog("​initiating call to %s from %s", NUMBER, audesc);
 +
 +                if (nb_voice_call_dial(call) == 0) {
 +                    nb_syslog("​unable to initate call to %s", NUMBER);
 +                }
 +            } else {
 +                nb_syslog("​not calling %s as endpoint %s is not available",​ NUMBER, audesc);
 +                return -1;
 +            }
 +        } else {
 +            nb_syslog("​DI1 has been opened"​);​
 +
 +            /* terminate any active calls */
 +            for (i = 0; i < length(calls);​ i++) {
 +                call = calls[i];
 +
 +                if (strstr(struct_get(call,​ "​called"​),​ desc)) {
 +                    nb_syslog("​hanging up call %d", struct_get(call,​ "​id"​));​
 +                    nb_voice_call_hangup(call);​
 +                }
 +            }
 +        }
 +
 +        return 0;
 +    }
 +
 +    void handle_voice_event (struct event)
 +    {
 +        type = struct_get(event,​ "​type"​);​
 +        call = struct_get(event,​ "​call"​);​
 +        id = struct_get(call,​ "​id"​);​
 +
 +        nb_syslog("​received voice event '​%s'​ on call %d\n", type, id);
 +
 +        /* update endpoint */
 +        au = nb_voice_endpoint_get(d.audio);​
 +        if (!is_struct(au)) {
 +            nb_syslog("​updating audio endpoint failed"​);​
 +            return;
 +        }
 +        austate = struct_get(au,​ "​state"​);​
 +        audesc = struct_get(au,​ "​desc"​);​
 +        ​
 +        switch (type) {
 +            case "​outgoing":​
 +                /* don't touch any locally initiated calls */
 +                break;
 +            case "​incoming":​
 +                nb_syslog("​call %s: %s is calling %s",
 +                          id, struct_get(call,​ "​calling"​),​ struct_get(call,​ "​called"​));​
 +
 +                /* route any incoming calls to audio device */
 +                if (nb_voice_call_route(call,​ audesc) == 0) {
 +                    nb_syslog("​routing call %d to %s", id, audesc);
 +                } else {
 +                    nb_syslog("​unable to route call %d to %s", id, audesc);
 +                    nb_voice_call_hangup(call);​
 +                }
 +                break;
 +            case "​dispatched":​
 +                /* accept calls if DI1 closes */
 +
 +                nb_syslog("​call %s: %s to %s got dispatched",​
 +                          id, struct_get(call,​ "​calling"​),​ struct_get(call,​ "​called"​));​
 +
 +                if (struct_get(call,​ "​state"​) == "​alerting"​) { 
 +                    if (austate == "​available"​) {
 +                        nb_syslog("​hanging up call %d as audio is busy", id);
 +                        nb_voice_call_hangup(call);​
 +                    } else {
 +                        /* wait until IN1 has been closed */
 +                        nb_syslog("​waiting 10s until IN1 is closed"​);​
 +                        for (i = 0; i < 10; i++) {
 +                            in1 = this.checkdio();​
 +                            if (in1 == 1) {
 +                                nb_syslog("​IN1 closed"​);​
 +
 +                                if (nb_voice_call_accept(call) == 0) {
 +                                    nb_syslog("​accepted call %d", id);
 +
 +                                    if (1) {
 +                                        /* increase volume level */
 +                                        nb_voice_call_volume(call,​ 7);
 +                                    }
 +
 +                                    return;
 +                                } else {
 +                                    nb_syslog("​unable to accept call %d", id);
 +                                    break;
 +                                }
 +                            }
 +                            sleep(1);
 +                        }
 +                    }
 +                    /* otherwise hangup */
 +                    nb_syslog("​hanging up call %d", id);
 +                    nb_voice_call_hangup(call);​
 +                }
 +                break;
 +            default:
 +                break;
 +        }
 +    }
 +
 +    void run ()
 +    {
 +        /* wait for calls */
 +        while (1) {
 +            event = nb_voice_event(INTERVAL);​
 +            if (is_struct(event)) {
 +                dump(event);​
 +                this.handle_voice_event(event);​
 +            } 
 +            event = this.checkdio();​
 +            if (event != -1) {
 +                this.handle_dio_event(event);​
 +            }
 +        }
 +    }
 +}
 +
 +d = new dispatcher();​
 +dump(d);
 +d.run();
 +
 +exit(0);
 +
 +</​code>​