aboutsummaryrefslogtreecommitdiffstats
path: root/devicestate.c
diff options
context:
space:
mode:
authoroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-06-26 16:43:21 +0000
committeroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-06-26 16:43:21 +0000
commit653b869cfdf3128de920f1a954a590cc398655f2 (patch)
tree7c4ae410cac4ecff766920eb510930499d5d5a19 /devicestate.c
parentf6f781f7896a25862974ea01825fa16d2b8882f2 (diff)
METERMAIDS:
----------- - Adding devicestate providers, a new architecture to add non-channel related device state information, like parking lots, queues, meetmes, vending machines and Windows 98 reboots (lots of blinking on those lights) - Adding provider for parking lots, so you can subscribe to the status of a parking lot - Adding provider for meetme, so you can have a blinking lamp for a meetme ( Example: exten => edvina,hint,meetme:1234 ) - Adding support for directed parking - set the PARKINGEXTEN before you manually call Park() and you will be parked on that space. If it's occupied, dialplan execution will continue. This work was sponsored by Voop A/S - www.voop.com git-svn-id: http://svn.digium.com/svn/asterisk/trunk@36055 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'devicestate.c')
-rw-r--r--devicestate.c117
1 files changed, 109 insertions, 8 deletions
diff --git a/devicestate.c b/devicestate.c
index 4121cfbcb..b0e5d5aec 100644
--- a/devicestate.c
+++ b/devicestate.c
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/logger.h"
#include "asterisk/devicestate.h"
#include "asterisk/pbx.h"
+#include "asterisk/app.h"
#include "asterisk/options.h"
/*! \brief Device state strings for printing */
@@ -53,6 +54,16 @@ static const char *devstatestring[] = {
/* 6 AST_DEVICE_RINGING */ "Ringing" /*!< Ring, ring, ring */
};
+/*! \brief A device state provider (not a channel) */
+struct devstate_prov {
+ char label[40];
+ ast_devstate_prov_cb_type callback;
+ AST_LIST_ENTRY(devstate_prov) list;
+};
+
+/*! \brief A list of providers */
+static AST_LIST_HEAD_STATIC(devstate_provs, devstate_prov);
+
/*! \brief A device state watcher (callback) */
struct devstate_cb {
void *data;
@@ -60,6 +71,7 @@ struct devstate_cb {
AST_LIST_ENTRY(devstate_cb) list;
};
+/*! \brief A device state watcher list */
static AST_LIST_HEAD_STATIC(devstate_cbs, devstate_cb);
struct state_change {
@@ -67,11 +79,19 @@ struct state_change {
char device[1];
};
+/*! \brief The state change queue. State changes are queued
+ for processing by a separate thread */
static AST_LIST_HEAD_STATIC(state_changes, state_change);
+/*! \brief The device state change notification thread */
static pthread_t change_thread = AST_PTHREADT_NULL;
+
+/*! \brief Flag for the queue */
static ast_cond_t change_pending;
+/* Forward declarations */
+static int getproviderstate(const char *provider, const char *address);
+
/*! \brief Find devicestate as text message for output */
const char *devstate2str(int devstate)
{
@@ -79,9 +99,9 @@ const char *devstate2str(int devstate)
}
/*! \brief Find out if device is active in a call or not
-\note find channels with the device's name in it
-This function is only used for channels that does not implement
-devicestate natively
+ \note find channels with the device's name in it
+ This function is only used for channels that does not implement
+ devicestate natively
*/
int ast_parse_device_state(const char *device)
{
@@ -110,17 +130,34 @@ int ast_parse_device_state(const char *device)
int ast_device_state(const char *device)
{
char *buf;
- char *tech;
char *number;
const struct ast_channel_tech *chan_tech;
int res = 0;
+ /*! \brief Channel driver that provides device state */
+ char *tech;
+ /*! \brief Another provider of device state */
+ char *provider = NULL;
buf = ast_strdupa(device);
tech = strsep(&buf, "/");
number = buf;
- if (!number)
- return AST_DEVICE_INVALID;
-
+ if (!number) {
+ provider = strsep(&tech, ":");
+ if (!provider)
+ return AST_DEVICE_INVALID;
+ /* We have a provider */
+ number = tech;
+ tech = NULL;
+ }
+
+ if (provider) {
+ if(option_debug > 2)
+ ast_log(LOG_DEBUG, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number);
+ return getproviderstate(provider, number);
+ }
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "No provider found, checking channel drivers for %s - %s\n", tech, number);
+
chan_tech = ast_get_channel_tech(tech);
if (!chan_tech)
return AST_DEVICE_INVALID;
@@ -143,6 +180,63 @@ int ast_device_state(const char *device)
}
}
+/*! \brief Add device state provider */
+int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
+{
+ struct devstate_prov *devprov;
+
+ if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov))))
+ return -1;
+
+ devprov->callback = callback;
+ ast_copy_string(devprov->label, label, sizeof(devprov->label));
+
+ AST_LIST_LOCK(&devstate_provs);
+ AST_LIST_INSERT_HEAD(&devstate_provs, devprov, list);
+ AST_LIST_UNLOCK(&devstate_provs);
+
+ return 0;
+}
+
+/*! \brief Remove device state provider */
+void ast_devstate_prov_del(const char *label)
+{
+ struct devstate_prov *devcb;
+
+ AST_LIST_LOCK(&devstate_provs);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) {
+ if (!strcasecmp(devcb->label, label)) {
+ AST_LIST_REMOVE_CURRENT(&devstate_provs, list);
+ free(devcb);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+ AST_LIST_UNLOCK(&devstate_provs);
+}
+
+/*! \brief Get provider device state */
+static int getproviderstate(const char *provider, const char *address)
+{
+ struct devstate_prov *devprov;
+ int res = AST_DEVICE_INVALID;
+
+
+ AST_LIST_LOCK(&devstate_provs);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devprov, list) {
+ if(option_debug > 4)
+ ast_log(LOG_DEBUG, "Checking provider %s with %s\n", devprov->label, provider);
+
+ if (!strcasecmp(devprov->label, provider)) {
+ res = devprov->callback(address);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+ AST_LIST_UNLOCK(&devstate_provs);
+ return res;
+}
+
/*! \brief Add device state watcher */
int ast_devstate_add(ast_devstate_cb_type callback, void *data)
{
@@ -178,7 +272,9 @@ void ast_devstate_del(ast_devstate_cb_type callback, void *data)
AST_LIST_UNLOCK(&devstate_cbs);
}
-/*! \brief Notify callback watchers of change, and notify PBX core for hint updates */
+/*! \brief Notify callback watchers of change, and notify PBX core for hint updates
+ Normally executed within a separate thread
+*/
static void do_state_change(const char *device)
{
int state;
@@ -201,10 +297,15 @@ static int __ast_device_state_changed_literal(char *buf)
char *device, *tmp;
struct state_change *change;
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Notification of state change to be queued on device/channel %s\n", buf);
+
device = buf;
if ((tmp = strrchr(device, '-')))
*tmp = '\0';
+
+
if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
/* we could not allocate a change struct, or */
/* there is no background thread, so process the change now */