134 static char *app =
"SkelGuessNumber";
137 OPTION_CHEAT = (1 << 0),
138 OPTION_NUMGAMES = (1 << 1),
144 OPTION_ARG_ARRAY_SIZE,
194 uint32_t total_games;
201 #define LEVEL_BUCKETS 1
244 .item_offset = offsetof(
struct skel_config, global),
246 .category =
"general",
255 .item_offset = offsetof(
struct skel_config, global),
257 .category =
"sounds",
262 static const char *level_categories[] = {
273 .category = (
const char *)level_categories,
283 .types =
ACO_TYPES(&global_option, &sound_option, &level_option),
294 .files = ACO_FILES(&app_skel_conf),
297 static void skel_global_config_destructor(
void *obj)
303 static void skel_game_destructor(
void *obj)
309 static void skel_state_destructor(
void *obj)
317 if (!(game = ao2_alloc(
sizeof(
struct skel_current_game), skel_game_destructor))) {
325 static void skel_level_destructor(
void *obj)
329 ao2_cleanup(level->
state);
332 static int skel_level_hash(
const void *obj,
const int flags)
339 static int skel_level_cmp(
void *obj,
void *arg,
int flags)
342 const char *match = (flags &
OBJ_KEY) ? arg : two->
name;
360 if (!strcasecmp(var->
name,
"cheat")) {
369 static void play_files_helper(
struct ast_channel *chan,
const char *prompts)
380 static int app_exec(
struct ast_channel *chan,
const char *data)
387 char *parse, *opts[OPTION_ARG_ARRAY_SIZE];
395 ast_log(LOG_ERROR,
"Couldn't access configuratino data!\n");
399 if (ast_strlen_zero(data)) {
400 ast_log(LOG_WARNING,
"%s requires an argument (level[,options])\n", app);
409 if (args.argc == 2) {
413 if (ast_strlen_zero(args.level)) {
414 ast_log(LOG_ERROR,
"%s requires a level argument\n", app);
418 if (!(level = ao2_find(cfg->levels, args.level,
OBJ_KEY))) {
419 ast_log(LOG_ERROR,
"Unknown level: %s\n", args.level);
423 if (!(game = skel_game_alloc(level))) {
430 if (!ast_test_flag(&flags, OPTION_NUMGAMES) ||
431 ast_strlen_zero(opts[OPTION_ARG_NUMGAMES]) ||
432 ast_parse_arg(opts[OPTION_ARG_NUMGAMES], PARSE_UINT32, &game->total_games)) {
433 game->total_games = cfg->global->num_games;
436 game->
cheat = ast_test_flag(&flags, OPTION_CHEAT) || cfg->global->cheat;
439 uint32_t num = ast_random() % level->
max_num;
441 ast_debug(1,
"They should totally should guess %u\n", num);
444 play_files_helper(chan, cfg->global->prompt);
447 for (guesses = 0; guesses < level->
max_guesses; guesses++) {
448 size_t buflen = log10(level->
max_num) + 1;
456 if (guesses < level->max_guesses - 1) {
457 play_files_helper(chan, cfg->global->wrong);
463 if (guess == num && !game->
cheat) {
466 play_files_helper(chan, cfg->global->right);
469 }
else if (guess < num) {
470 play_files_helper(chan, cfg->global->low);
472 play_files_helper(chan, cfg->global->high);
475 if (guesses < level->max_guesses - 1) {
476 play_files_helper(chan, cfg->global->wrong);
481 ao2_lock(level->
state);
488 play_files_helper(chan, cfg->global->lose);
490 ao2_unlock(level->
state);
498 static struct skel_level *skel_state_alloc(
const char *name)
502 if (!(level = ao2_alloc(
sizeof(*level), skel_state_destructor))) {
511 return ao2_find(tmp_container, category,
OBJ_KEY);
526 if (!cfg || !cfg->levels || !(level = ao2_find(cfg->levels, category,
OBJ_KEY))) {
527 return skel_state_alloc(category);
537 if (!(level = ao2_alloc(
sizeof(*level), skel_level_destructor))) {
560 static void skel_config_destructor(
void *obj)
563 ao2_cleanup(cfg->global);
564 ao2_cleanup(cfg->levels);
571 if (!(cfg = ao2_alloc(
sizeof(*cfg), skel_config_destructor))) {
576 if (!(cfg->global = ao2_alloc(
sizeof(*cfg->global), skel_global_config_destructor))) {
585 skel_level_hash, NULL, skel_level_cmp);
602 e->
command =
"skel show config";
604 "Usage: skel show config\n"
605 " List app_skel global config\n";
615 ast_cli(a->fd,
"games per call: %u\n", cfg->global->num_games);
616 ast_cli(a->fd,
"computer cheats: %s\n",
AST_CLI_YESNO(cfg->global->cheat));
617 ast_cli(a->fd,
"\n");
618 ast_cli(a->fd,
"Sounds\n");
619 ast_cli(a->fd,
" prompt: %s\n", cfg->global->prompt);
620 ast_cli(a->fd,
" wrong guess: %s\n", cfg->global->wrong);
621 ast_cli(a->fd,
" right guess: %s\n", cfg->global->right);
633 e->
command =
"skel show games";
635 "Usage: skel show games\n"
636 " List app_skel active games\n";
642 #define SKEL_FORMAT "%-15.15s %-15.15s %-15.15s\n"
643 #define SKEL_FORMAT1 "%-15.15s %-15u %-15u\n"
644 ast_cli(a->fd, SKEL_FORMAT,
"Level",
"Total Games",
"Games Left");
646 while ((game = ao2_iterator_next(&iter))) {
664 e->
command =
"skel show levels";
666 "Usage: skel show levels\n"
667 " List the app_skel levels\n";
677 #define SKEL_FORMAT "%-15.15s %-11.11s %-12.12s %-8.8s %-8.8s %-12.12s\n"
678 #define SKEL_FORMAT1 "%-15.15s %-11u %-12u %-8u %-8u %-8f\n"
679 ast_cli(a->fd, SKEL_FORMAT,
"Name",
"Max number",
"Max Guesses",
"Wins",
"Losses",
"Avg Guesses");
681 while ((level = ao2_iterator_next(&iter))) {
693 AST_CLI_DEFINE(handle_skel_show_config,
"Show app_skel global config options"),
694 AST_CLI_DEFINE(handle_skel_show_levels,
"Show app_skel levels"),
695 AST_CLI_DEFINE(handle_skel_show_games,
"Show app_skel active games"),
698 static int reload_module(
void)
707 static int unload_module(
void)
769 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,
"Skeleton (sample) Application",
770 .support_level = AST_MODULE_SUPPORT_CORE,
772 .unload = unload_module,
773 .reload = reload_module,
aco_type_item_find item_find
Main Channel structure associated with a channel.
Asterisk locking-related definitions:
const ast_string_field lose
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field wrong
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
String manipulation functions.
static struct aco_type sound_option
An aco_type structure to link the "sounds" category to the skel_global_config type.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
const ast_string_field right
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
descriptor for a cli entry.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Structure for variables, used for configurations and for channel variables.
static char * levels[NUMLOGLEVELS]
Logging channels used in the Asterisk logging system.
static void * skel_level_alloc(const char *cat)
Allocate a skel_level based on a category in a configuration file.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
const ast_string_field high
static AO2_GLOBAL_OBJ_STATIC(globals)
A global object container that will contain the skel_config that gets swapped out on reloads...
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
const ast_string_field prompt
The representation of a single configuration file to be processed.
int ast_unregister_application(const char *app)
Unregister an application.
struct skel_level * level_info
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
static struct ao2_container * games
The container of active games.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Configuration File Parser.
static int custom_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
A custom bitfield handler.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
General Asterisk PBX channel definitions.
Type for default option handler for unsigned integers.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Access Control of various sorts.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_STRING_FIELD(name)
Declare a string field.
const ast_string_field low
static struct aco_type level_option
An aco_type structure to link the everything but the "general" and "sounds" categories to the skel_le...
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
aco_type_item_alloc item_alloc
#define ast_debug(level,...)
Log a DEBUG message.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Core PBX routines and definitions.
struct skel_level_state * state
Their was an error and no changes were applied.
Configuration option-handling.
Object to hold level config information.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define ao2_unlink(container, obj)
Remove an object from a container.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
A container that holds all config-related information.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Module has failed to load, may be in an inconsistent state.
static struct aco_type global_option
An aco_type structure to link the "general" category to the skel_global_config type.
Structure used to handle boolean flags.
static void * skel_find_or_create_state(const char *category)
Look up an existing state object, or create a new one.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Standard Command Line Interface.
Type information about a category-level configurable object.
A structure to hold global configuration-related options.
const ast_string_field name
static void * skel_level_find(struct ao2_container *tmp_container, const char *category)
Find a skel level in the specified container.
A structure to maintain level state across reloads.
Type for default option handler for stringfields.
static int load_module(void)
Load the module.
CONFIG_INFO_STANDARD(cfg_info, globals, skel_config_alloc,.files=ACO_FILES(&app_skel_conf),)
Register information about the configs being processed by this module.
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
static void * skel_config_alloc(void)
Allocate a skel_config to hold a snapshot of the complete results of parsing a config.
Information about a currently running set of games.
#define ao2_link(container, obj)
Add an object to a container.