<para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
parking context, Park() will park the call on that extension, unless
it already exists. In that case, execution will continue at next priority.</para>
+ <para>If you set the <variable>PARKINGLOT</variable> variable, Park() will park the call
+ in that parkinglot.</para>
+ <para>If you set the <variable>PARKINGDYNAMIC</variable> variable, this parkinglot from features.conf
+ will be used as template for the newly created dynamic lot.</para>
+ <para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable the newly created dynamic
+ parking lot will use this context.</para>
+ <para>If you set the <variable>PARKINGDYNPOS</variable> variable the newly created dynamic parkinglot
+ will use those parking postitions.</para>
</description>
<see-also>
<ref type="application">ParkAndAnnounce</ref>
static char courtesytone[256]; /*!< Courtesy tone */
static int parkedplay = 0; /*!< Who to play the courtesy tone to */
+static int parkeddynamic = 0; /*!< Enable creation of parkinglots dynamically */
static char xfersound[256]; /*!< Call transfer sound */
static char xferfailsound[256]; /*!< Call transfer failure sound */
static char pickupsound[256]; /*!< Pickup sound */
static void parkinglot_destroy(void *obj);
int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
struct ast_parkinglot *find_parkinglot(const char *name);
-
+static struct ast_parkinglot *create_parkinglot(const char *name);
+static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
const char *ast_parking_ext(void)
{
struct parkeduser *pu;
};
-static struct parkeduser *park_space_reserve(struct ast_channel *chan,
- struct ast_channel *peer, struct ast_park_call_args *args)
+static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
{
struct parkeduser *pu;
int i, parking_space = -1, parking_range;
const char *parkinglotname = NULL;
const char *parkingexten;
struct ast_parkinglot *parkinglot = NULL;
-
+
if (peer)
parkinglotname = findparkinglotname(peer);
if (parkinglotname) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
- parkinglot = find_parkinglot(parkinglotname);
+ ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglotname);
+ parkinglot = find_parkinglot(parkinglotname);
+
}
+
+ /* Dynamically create parkinglot */
+ if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
+ const char *dyn_context, *dyn_range;
+ const char *parkinglotname_copy = NULL;
+ struct ast_parkinglot *parkinglot_copy = NULL;
+ int dyn_start, dyn_end;
+
+ ast_channel_lock(chan);
+ parkinglotname_copy = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
+ dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
+ dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
+ ast_channel_unlock(chan);
+
+ if (!ast_strlen_zero(parkinglotname_copy)) {
+ parkinglot_copy = find_parkinglot(parkinglotname_copy);
+ }
+ if (!parkinglot_copy) {
+ parkinglot_copy = parkinglot_addref(default_parkinglot);
+ ast_debug(1, "Using default parking lot for copy\n");
+ }
+ if (!(parkinglot = copy_parkinglot(parkinglotname, parkinglot_copy))) {
+ ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
+ } else {
+ if (!ast_strlen_zero(dyn_context)) {
+ ast_copy_string(parkinglot->parking_con, dyn_context, sizeof(parkinglot->parking_con));
+ }
+ if (!ast_strlen_zero(dyn_range)) {
+ if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
+ ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers\n");
+ } else {
+ parkinglot->parking_start = dyn_start;
+ parkinglot->parking_stop = dyn_end;
+ }
+ }
+ ao2_link(parkinglots, parkinglot);
+ }
+
+ if (parkinglot_copy) {
+ /* unref our tempory copy */
+ parkinglot_unref(parkinglot_copy);
+ parkinglot_copy = NULL;
+ }
+ }
+
if (!parkinglot) {
parkinglot = parkinglot_addref(default_parkinglot);
}
return parkinglot;
}
+/*! \brief Copy parkinglot and store it with new name */
+struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot) {
+ struct ast_parkinglot *copylot;
+
+ if (ast_strlen_zero(name)) { /* No name specified */
+ return NULL;
+ }
+ if (find_parkinglot(name)) { /* Parkinglot with that name allready exists */
+ return NULL;
+ }
+
+ copylot = create_parkinglot(name);
+ ast_debug(1, "Building parking lot %s\n", name);
+
+ memcpy(copylot, parkinglot, sizeof(struct ast_parkinglot));
+ ast_copy_string(copylot->name, name, sizeof(copylot->name));
+ AST_LIST_HEAD_INIT(©lot->parkings);
+
+ return copylot;
+}
+
AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
}
/*! \brief Allocate parking lot structure */
-static struct ast_parkinglot *create_parkinglot(char *name)
+static struct ast_parkinglot *create_parkinglot(const char *name)
{
struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
ao2_lock(parkinglot);
- if (option_debug)
- ast_log(LOG_DEBUG, "Building parking lot %s\n", name);
-
+ ast_debug(1, "Building parking lot %s\n", name);
+
/* Do some config stuff */
while(confvar) {
if (!strcasecmp(confvar->name, "context")) {
pickupfailsound[0] = '\0';
adsipark = 0;
comebacktoorigin = 1;
+ parkeddynamic = 0;
default_parkinglot->parkaddhints = 0;
default_parkinglot->parkedcalltransfers = 0;
default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
else if (!strcasecmp(var->value, "callee"))
default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
+ } else if (!strcasecmp(var->name, "parkeddynamic")) {
+ parkeddynamic = ast_true(var->value);
} else if (!strcasecmp(var->name, "adsipark")) {
adsipark = ast_true(var->value);
} else if (!strcasecmp(var->name, "transferdigittimeout")) {