int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod) { SCOPED_AO2WRLOCK(lock, interfaces); struct format_interface *format_interface; if (!interface->format_clone || !interface->format_destroy) { ast_log(LOG_ERROR, "Format interface for codec '%s' does not implement required callbacks\n", codec); return -1; } format_interface = ao2_find(interfaces, codec, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (format_interface) { ast_log(LOG_ERROR, "A format interface is already present for codec '%s'\n", codec); ao2_ref(format_interface, -1); return -1; } format_interface = ao2_alloc_options(sizeof(*format_interface) + strlen(codec) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!format_interface) { return -1; } format_interface->interface = interface; strcpy(format_interface->codec, codec); /* Safe */ /* Once registered a format interface cannot be unregistered. */ ast_module_shutdown_ref(mod); ao2_link_flags(interfaces, format_interface, OBJ_NOLOCK); ao2_ref(format_interface, -1); ast_verb(2, "Registered format interface for codec '%s'\n", codec); return 0; }
static int load_module(void) { ast_bridge_features_register(AST_BRIDGE_BUILTIN_HANGUP, feature_hangup, NULL); ast_bridge_features_register(AST_BRIDGE_BUILTIN_AUTOMON, feature_automonitor, NULL); ast_bridge_features_register(AST_BRIDGE_BUILTIN_AUTOMIXMON, feature_automixmonitor, NULL); /* This module cannot be unloaded until shutdown */ ast_module_shutdown_ref(ast_module_info->self); return AST_MODULE_LOAD_SUCCESS; }
int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod) { SCOPED_AO2WRLOCK(lock, codecs); struct ast_codec *codec_new; /* Some types have specific requirements */ if (codec->type == AST_MEDIA_TYPE_UNKNOWN) { ast_log(LOG_ERROR, "A media type must be specified for codec '%s'\n", codec->name); return -1; } else if (codec->type == AST_MEDIA_TYPE_AUDIO) { if (!codec->sample_rate) { ast_log(LOG_ERROR, "A sample rate must be specified for codec '%s' of type '%s'\n", codec->name, ast_codec_media_type2str(codec->type)); return -1; } } codec_new = ao2_find(codecs, codec, OBJ_SEARCH_OBJECT | OBJ_NOLOCK); if (codec_new) { ast_log(LOG_ERROR, "A codec with name '%s' of type '%s' and sample rate '%u' is already registered\n", codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate); ao2_ref(codec_new, -1); return -1; } codec_new = ao2_t_alloc_options(sizeof(*codec_new), codec_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, "")); if (!codec_new) { ast_log(LOG_ERROR, "Could not allocate a codec with name '%s' of type '%s' and sample rate '%u'\n", codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate); return -1; } *codec_new = *codec; codec_new->id = codec_id++; ao2_link_flags(codecs, codec_new, OBJ_NOLOCK); /* Once registered a codec can not be unregistered, and the module must persist until shutdown */ ast_module_shutdown_ref(mod); ast_verb(2, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n", ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->id); ao2_ref(codec_new, -1); return 0; }