コード例 #1
0
void populate_profile_menu_event(vmivr_profile_t *profile, vmivr_menu_profile_t *menu) {
	switch_xml_t cfg, xml, x_profiles, x_profile, x_keys, x_phrases, x_menus, x_menu;

	free_profile_menu_event(menu);

	if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
		goto end;
	}
	if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
		goto end;
	}

	if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile->name))) {
		if ((x_menus = switch_xml_child(x_profile, "menus"))) {
			if ((x_menu = switch_xml_find_child(x_menus, "menu", "name", menu->name))) {
				if ((x_keys = switch_xml_child(x_menu, "keys"))) {
					switch_event_import_xml(switch_xml_child(x_keys, "key"), "dtmf", "action", &menu->event_keys_dtmf);
					switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "dtmf", &menu->event_keys_action);
					switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "variable", &menu->event_keys_varname);
				}
				if ((x_phrases = switch_xml_child(x_menu, "phrases"))) {
					switch_event_import_xml(switch_xml_child(x_phrases, "phrase"), "name", "value", &menu->event_phrases);
				}
			}
		}
	}
end:
	if (xml)
		switch_xml_free(xml);
	return;

}
コード例 #2
0
static int launch_streams(const char *name)
{
	switch_xml_t cfg, xml, directory;
	int x = 0;

	if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
		return 0;
	}

	if (zstr(name)) {
		for (directory = switch_xml_child(cfg, "directory"); directory; directory = directory->next) {
			char *name = (char *) switch_xml_attr(directory, "name");
			char *path = (char *) switch_xml_attr(directory, "path");
			launch_thread(name, path, directory);
			x++;
		}
	} else if ((directory = switch_xml_find_child(cfg, "directory", "name", name))) {
		char *path = (char *) switch_xml_attr(directory, "path");
		launch_thread(name, path, directory);
		x++;
	}
	switch_xml_free(xml);

	return x;
}
コード例 #3
0
static dir_profile_t *load_profile(const char *profile_name)
{
	dir_profile_t *profile = NULL;
	switch_xml_t x_profiles, x_profile, cfg, xml = NULL;
	switch_event_t *event = NULL;

	if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
		return profile;
	}
	if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
		goto end;
	}

	if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile_name))) {
		switch_memory_pool_t *pool;
		int count;

		if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n");
			goto end;
		}

		if (!(profile = switch_core_alloc(pool, sizeof(dir_profile_t)))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n");
			switch_core_destroy_memory_pool(&pool);
			goto end;
		}

		profile->pool = pool;
		profile_set_config(profile);

		/* Add the params to the event structure */
		count = (int)switch_event_import_xml(switch_xml_child(x_profile, "param"), "name", "value", &event);

		if (switch_xml_config_parse_event(event, count, SWITCH_FALSE, profile->config) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to process configuration\n");
			switch_core_destroy_memory_pool(&pool);
			goto end;
		}

		switch_thread_rwlock_create(&profile->rwlock, pool);
		profile->name = switch_core_strdup(pool, profile_name);

		switch_mutex_init(&profile->mutex, SWITCH_MUTEX_NESTED, profile->pool);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added Profile %s\n", profile->name);
		switch_core_hash_insert(globals.profile_hash, profile->name, profile);
	}

  end:
	switch_xml_free(xml);

	return profile;
}
コード例 #4
0
SWITCH_DECLARE(void) switch_nat_republish(void)
{
	switch_xml_t natxml = NULL;
	switch_xml_t row = NULL;
	switch_xml_t child = NULL;
	switch_stream_handle_t stream = { 0 };
	SWITCH_STANDARD_STREAM(stream);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Refreshing nat maps\n");

	switch_api_execute("show", "nat_map as xml", NULL, &stream);

	if (!(natxml = switch_xml_parse_str_dup(stream.data))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to parse XML: %s\n", (char *) stream.data);
		switch_safe_free(stream.data);
		return;
	}

	/* iterate the xml and publish the mappings */
	row = switch_xml_find_child(natxml, "row", "row_id", "1");
	while (row != NULL) {
		char *sport = NULL;
		char *sproto = NULL;
		switch_port_t port;
		switch_nat_ip_proto_t proto;

		if ((child = switch_xml_child(row, "port"))) {
			sport = child->txt;
		}
		if ((child = switch_xml_child(row, "proto_num"))) {
			sproto = child->txt;
		}

		if (sport && sproto) {
			port = (switch_port_t) (atoi(sport));
			proto = (switch_nat_ip_proto_t) (atoi(sproto));
			switch_nat_add_mapping_internal(port, proto, NULL, SWITCH_FALSE, SWITCH_FALSE);
		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to parse port/proto info: XML: %s\n", (char *) stream.data);
		}

		row = switch_xml_next(row);
	}

	switch_safe_free(stream.data);
	switch_xml_free(natxml);
}
コード例 #5
0
ファイル: switch_ivr_menu.c プロジェクト: hsaid/FreeSWITCH
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_stack_xml_build(switch_ivr_menu_xml_ctx_t *xml_menu_ctx,
																switch_ivr_menu_t ** menu_stack, switch_xml_t xml_menus, switch_xml_t xml_menu)
{
	switch_status_t status = SWITCH_STATUS_FALSE;

	if (xml_menu_ctx != NULL && menu_stack != NULL && xml_menu != NULL) {
		const char *menu_name = switch_xml_attr_soft(xml_menu, "name");	/* if the attr doesn't exist, return "" */
		const char *greet_long = switch_xml_attr(xml_menu, "greet-long");	/* if the attr doesn't exist, return NULL */
		const char *greet_short = switch_xml_attr(xml_menu, "greet-short");	/* if the attr doesn't exist, return NULL */
		const char *invalid_sound = switch_xml_attr(xml_menu, "invalid-sound");	/* if the attr doesn't exist, return NULL */
		const char *exit_sound = switch_xml_attr(xml_menu, "exit-sound");	/* if the attr doesn't exist, return NULL */
		const char *timeout = switch_xml_attr_soft(xml_menu, "timeout");	/* if the attr doesn't exist, return "" */
		const char *max_failures = switch_xml_attr_soft(xml_menu, "max-failures");	/* if the attr doesn't exist, return "" */
		const char *max_timeouts = switch_xml_attr_soft(xml_menu, "max-timeouts");
		const char *confirm_macro = switch_xml_attr(xml_menu, "confirm-macro");
		const char *confirm_key = switch_xml_attr(xml_menu, "confirm-key");
		const char *tts_engine = switch_xml_attr(xml_menu, "tts-engine");
		const char *tts_voice = switch_xml_attr(xml_menu, "tts-voice");
		const char *confirm_attempts = switch_xml_attr_soft(xml_menu, "confirm-attempts");
		const char *digit_len = switch_xml_attr_soft(xml_menu, "digit-len");
		const char *inter_timeout = switch_xml_attr_soft(xml_menu, "inter-digit-timeout");

		switch_ivr_menu_t *menu = NULL;

		if (zstr(max_timeouts)) {
			max_timeouts = max_failures;
		}

		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "building menu '%s'\n", menu_name);

		status = switch_ivr_menu_init(&menu,
									  *menu_stack,
									  menu_name,
									  greet_long,
									  greet_short,
									  invalid_sound,
									  exit_sound,
									  confirm_macro,
									  confirm_key,
									  tts_engine,
									  tts_voice,
									  atoi(confirm_attempts),
									  atoi(inter_timeout),
									  atoi(digit_len),
									  atoi(timeout),
									  strlen(max_failures) ? atoi(max_failures) : 0, strlen(max_timeouts) ? atoi(max_timeouts) : 0, xml_menu_ctx->pool);
		/* set the menu_stack for the caller */
		if (status == SWITCH_STATUS_SUCCESS && *menu_stack == NULL) {
			*menu_stack = menu;

			if (xml_menu_ctx->autocreated) {
				switch_set_flag(menu, SWITCH_IVR_MENU_FLAG_FREEPOOL);
			}
		}

		if (status == SWITCH_STATUS_SUCCESS && menu != NULL) {
			switch_xml_t xml_kvp;

			/* build menu entries */
			for (xml_kvp = switch_xml_child(xml_menu, "entry"); xml_kvp != NULL && status == SWITCH_STATUS_SUCCESS; xml_kvp = xml_kvp->next) {
				const char *action = switch_xml_attr(xml_kvp, "action");
				const char *digits = switch_xml_attr(xml_kvp, "digits");
				const char *param = switch_xml_attr_soft(xml_kvp, "param");

				if (is_valid_action(action) && !zstr(digits)) {
					switch_ivr_menu_xml_map_t *xml_map = xml_menu_ctx->map;
					int found = 0;

					/* find and appropriate xml handler */
					while (xml_map != NULL && !found) {
						if (!(found = (strcasecmp(xml_map->name, action) == 0))) {
							xml_map = xml_map->next;
						}
					}

					if (found && xml_map != NULL) {
						/* do we need to build a new sub-menu ? */
						if (xml_map->action == SWITCH_IVR_ACTION_EXECMENU && switch_ivr_menu_find(*menu_stack, param) == NULL) {
							if ((xml_menu = switch_xml_find_child(xml_menus, "menu", "name", param)) != NULL) {
								status = switch_ivr_menu_stack_xml_build(xml_menu_ctx, menu_stack, xml_menus, xml_menu);
							}
						}
						/* finally bind the menu entry */
						if (status == SWITCH_STATUS_SUCCESS) {
							if (xml_map->function != NULL) {
								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
												  "binding menu caller control '%s'/'%s' to '%s'\n", xml_map->name, param, digits);
								status = switch_ivr_menu_bind_function(menu, xml_map->function, param, digits);
							} else {
								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "binding menu action '%s' to '%s'\n", xml_map->name, digits);
								status = switch_ivr_menu_bind_action(menu, xml_map->action, param, digits);
							}
						}
					}
				} else {
					status = SWITCH_STATUS_FALSE;
				}
			}
		}
	}

	if (status != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to build xml menu\n");
	}

	return status;
}
コード例 #6
0
ファイル: config.c プロジェクト: konradwyr/FreeSwitch
void menu_init(vmivr_profile_t *profile, vmivr_menu_t *menu) {
	switch_xml_t cfg, xml, x_profiles, x_profile, x_keys, x_phrases, x_menus, x_menu, x_settings;

	menu->profile = profile;

	if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
		goto end;
	}
	if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No profiles group\n");
		goto end;
	}

	if (profile->event_settings) {
		/* TODO Replace this with a switch_event_merge_not_set(...) */
		switch_event_t *menu_default;
		switch_event_create(&menu_default, SWITCH_EVENT_REQUEST_PARAMS);
		if (menu->event_settings) {
			switch_event_merge(menu_default, menu->event_settings);
			switch_event_destroy(&menu->event_settings);
		}
		
		switch_event_create(&menu->event_settings, SWITCH_EVENT_REQUEST_PARAMS);
		switch_event_merge(menu->event_settings, profile->event_settings);
		switch_event_merge(menu->event_settings, menu_default);
		switch_event_destroy(&menu_default);
	}

	{
		const char *s_max_attempts = switch_event_get_header(menu->event_settings, "IVR-Maximum-Attempts");
		const char *s_entry_timeout = switch_event_get_header(menu->event_settings, "IVR-Entry-Timeout");
		menu->ivr_maximum_attempts = atoi(s_max_attempts);
		menu->ivr_entry_timeout = atoi(s_entry_timeout);
	}

	if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile->name))) {
		if ((x_menus = switch_xml_child(x_profile, "menus"))) {
			if ((x_menu = switch_xml_find_child(x_menus, "menu", "name", menu->name))) {

				if ((x_keys = switch_xml_child(x_menu, "keys"))) {
					switch_event_import_xml(switch_xml_child(x_keys, "key"), "dtmf", "action", &menu->event_keys_dtmf);
					switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "dtmf", &menu->event_keys_action);
					switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "variable", &menu->event_keys_varname);
				}
				if ((x_phrases = switch_xml_child(x_menu, "phrases"))) {
					switch_event_import_xml(switch_xml_child(x_phrases, "phrase"), "name", "value", &menu->event_phrases);
				}
				if ((x_settings = switch_xml_child(x_profile, "settings"))) {
					switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &menu->event_settings);
				}

			}
		}
	}
end:
	if (xml)
		switch_xml_free(xml);
	return;

}
コード例 #7
0
ファイル: config.c プロジェクト: konradwyr/FreeSwitch
vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile_name)
{
	vmivr_profile_t *profile = NULL;
	switch_xml_t cfg, xml, x_profiles, x_profile, x_apis, x_settings, param;

	if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
		return profile;
	}
	if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
		goto end;
	}

	if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile_name))) {
		if (!(profile = switch_core_session_alloc(session, sizeof(vmivr_profile_t)))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n");
			goto end;	
		}

		profile->name = profile_name;

		profile->current_msg = 0;
		profile->current_msg_uuid = NULL;

		profile->folder_name = VM_FOLDER_ROOT;
		profile->folder_filter = VM_MSG_NOT_READ;

		/* TODO Make the following configurable */
		profile->api_profile = profile->name;
		profile->menu_check_auth = "std_authenticate";
		profile->menu_check_main = "std_main_menu";
		profile->menu_check_terminate = "std_purge";

		/* Populate default general settings */
		switch_event_create(&profile->event_settings, SWITCH_EVENT_REQUEST_PARAMS);
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "IVR-Maximum-Attempts", "%d", 3);
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "IVR-Entry-Timeout", "%d", 3000);
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Exit-Purge", "%s", "true");
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Password-Mask", "%s", "XXX.");
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "User-Mask", "%s", "X.");
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Format", "%s", "wav");
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Silence-Hits", "%d", 4);
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Silence-Threshold", "%d", 200);
		switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Maximum-Length", "%d", 30);

		if ((x_settings = switch_xml_child(x_profile, "settings"))) {
			switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &profile->event_settings);
		}

		if ((x_apis = switch_xml_child(x_profile, "apis"))) {
			int total_options = 0;
			int total_invalid_options = 0;
			for (param = switch_xml_child(x_apis, "api"); param; param = param->next) {
				char *var, *val;
				if ((var = (char *) switch_xml_attr_soft(param, "name")) && (val = (char *) switch_xml_attr_soft(param, "value"))) {
					if (!strcasecmp(var, "msg_undelete") && !profile->api_msg_undelete)
						profile->api_msg_undelete = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_delete") && !profile->api_msg_delete)
						profile->api_msg_delete = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_list") && !profile->api_msg_list)
						profile->api_msg_list = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_count") && !profile->api_msg_count)
						profile->api_msg_count = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_save") && !profile->api_msg_save)
						profile->api_msg_save = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_purge") && !profile->api_msg_purge)
						profile->api_msg_purge = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_get") && !profile->api_msg_get)
						profile->api_msg_get = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_forward") && !profile->api_msg_forward)
						profile->api_msg_forward = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "pref_greeting_set") && !profile->api_pref_greeting_set)
						profile->api_pref_greeting_set = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "pref_recname_set") && !profile->api_pref_recname_set)
						profile->api_pref_recname_set = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "pref_password_set") && !profile->api_pref_password_set)
						profile->api_pref_password_set = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "auth_login") && !profile->api_auth_login)
						profile->api_auth_login = switch_core_session_strdup(session, val);
					else
						total_invalid_options++;
					total_options++;
				}
			}
			if (total_options - total_invalid_options != 12) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing api definition for profile '%s'\n", profile_name);
				profile = NULL;
			}
		}

	}

end:
	switch_xml_free(xml);
	return profile;
}
コード例 #8
0
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj)
{
	local_stream_source_t *source = obj;
	switch_file_handle_t fh = { 0 };
	local_stream_context_t *cp;
	char file_buf[128] = "", path_buf[512] = "";
	switch_timer_t timer = { 0 };
	int fd = -1;
	switch_buffer_t *audio_buffer;
	switch_byte_t *dist_buf;
	switch_size_t used;
	int skip = 0;
	switch_memory_pool_t *temp_pool = NULL;

	switch_mutex_lock(globals.mutex);
	THREADS++;
	switch_mutex_unlock(globals.mutex);

	if (!source->prebuf) {
		source->prebuf = DEFAULT_PREBUFFER_SIZE;
	}

	switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0);
	dist_buf = switch_core_alloc(source->pool, source->prebuf + 10);

	if (source->shuffle) {
		skip = do_rand();
	}

	switch_thread_rwlock_create(&source->rwlock, source->pool);

	if (RUNNING) {
		switch_mutex_lock(globals.mutex);
		switch_core_hash_insert(globals.source_hash, source->name, source);
		switch_mutex_unlock(globals.mutex);
		source->ready = 1;
	}

	while (RUNNING && !source->stopped) {
		const char *fname;

		if (temp_pool) {
			switch_core_destroy_memory_pool(&temp_pool);
		}

		if (switch_core_new_memory_pool(&temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error creating pool");
			goto done;
		}

		if (switch_dir_open(&source->dir_handle, source->location, temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't open directory: %s\n", source->location);
			goto done;
		}

		switch_yield(1000000);

		while (RUNNING && !source->stopped) {
			switch_size_t olen;
			uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };

			if (fd > -1) {
				char *p;
				if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
					if ((p = strchr(path_buf, '\r')) || (p = strchr(path_buf, '\n'))) {
						*p = '\0';
					}
				} else {
					close(fd);
					fd = -1;
					continue;
				}
			} else {
				if (!(fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) {
					break;
				}

				switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname);

				if (switch_stristr(".loc", path_buf)) {
					if ((fd = open(path_buf, O_RDONLY)) < 0) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
						switch_yield(1000000);
					}
					continue;
				}
			}

			if (skip > 0) {
				skip--;
				continue;
			}

			fname = path_buf;
			fh.prebuf = source->prebuf;
			fh.pre_buffer_datalen = source->prebuf;

			if (switch_core_file_open(&fh,
									  (char *) fname,
									  source->channels, source->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
				switch_yield(1000000);
				continue;
			}

			if (switch_core_timer_init(&timer, source->timer_name, source->interval, (int)source->samples, temp_pool) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
				switch_dir_close(source->dir_handle);
				source->dir_handle = NULL;
				goto done;
			}

			while (RUNNING && !source->stopped) {
				int is_open;
				switch_file_handle_t *use_fh = &fh;

				switch_core_timer_next(&timer);
				olen = source->samples;

				if (source->chime_total) {

					if (source->chime_counter > 0) {
						source->chime_counter -= (int32_t)source->samples;
					}

					if (!switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN) && source->chime_counter <= 0) {
						char *val;

						val = source->chime_list[source->chime_cur++];

						if (source->chime_cur >= source->chime_total) {
							source->chime_cur = 0;
						}

						if (switch_core_file_open(&source->chime_fh,
												  (char *) val,
												  source->channels,
												  source->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", val);
						}
					}

					if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
						use_fh = &source->chime_fh;
					}
				}

			  retry:

				is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);

				if (source->hup) {
					source->hup = 0;
					if (is_open) {
						is_open = 0;

						switch_core_file_close(use_fh);
						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
							use_fh = &fh;
							goto retry;
							//switch_core_file_close(&fh);
						}
					}
				}



				if (is_open) {
					if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
						switch_core_file_close(use_fh);
						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
						}
						is_open = 0;
					} else {
						if (use_fh == &source->chime_fh && source->chime_max) {
							source->chime_max_counter += (int32_t)source->samples;
							if (source->chime_max_counter >= source->chime_max) {
								source->chime_max_counter = 0;
								switch_core_file_close(use_fh);
								source->chime_counter = source->rate * source->chime_freq;
								use_fh = &fh;
								goto retry;
							}
						}

						switch_buffer_write(audio_buffer, abuf, olen * 2);
					}
				}

				used = switch_buffer_inuse(audio_buffer);

				if (!used && !is_open) {
					break;
				}

				if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) {
					used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2);
					if (source->total) {
						uint32_t bused = 0;
						switch_mutex_lock(source->mutex);
						for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
							if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
								continue;
							}
							switch_mutex_lock(cp->audio_mutex);
							bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer);
							if (bused > source->samples * 768) {
								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", 
												  cp->func, cp->file, cp->line, bused, (long)source->samples);
								switch_buffer_zero(cp->audio_buffer);
							} else {
								switch_buffer_write(cp->audio_buffer, dist_buf, used);
							}
							switch_mutex_unlock(cp->audio_mutex);
						}
						switch_mutex_unlock(source->mutex);
					}
				}
			}

			switch_core_timer_destroy(&timer);
			if (RUNNING && source->shuffle) {
				skip = do_rand();
			}
		}

		switch_dir_close(source->dir_handle);
		source->dir_handle = NULL;

		if (source->full_reload) {
			if (source->rwlock && switch_thread_rwlock_trywrlock(source->rwlock) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot stop local_stream://%s because it is in use.\n",source->name);
				if (source->part_reload) {
					switch_xml_t cfg, xml, directory, param;
					if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
					}
					if ((directory = switch_xml_find_child(cfg, "directory", "name", source->name))) {
						for (param = switch_xml_child(directory, "param"); param; param = param->next) {
							char *var = (char *) switch_xml_attr_soft(param, "name");
							char *val = (char *) switch_xml_attr_soft(param, "value");
							if (!strcasecmp(var, "shuffle")) {
								source->shuffle = switch_true(val);
							} else if (!strcasecmp(var, "chime-freq")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_freq = tmp;
								}
							} else if (!strcasecmp(var, "chime-max")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_max = tmp;
								}
							} else if (!strcasecmp(var, "chime-list")) {
								char *list_dup = switch_core_strdup(source->pool, val);
								source->chime_total =
									switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0])));
							} else if (!strcasecmp(var, "interval")) {
								int tmp = atoi(val);
								if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
									source->interval = tmp;
								} else {
									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
													  "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
								}
							}
							if (source->chime_max) {
								source->chime_max *= source->rate;
							}
							if (source->chime_total) {
								source->chime_counter = source->rate * source->chime_freq;
							}
						}
					}
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name);
					source->part_reload = 0;
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name);
				launch_streams(source->name);
				goto done;
			}
		}
	}

  done:

	if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&fh);
	}

	if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&source->chime_fh);
	}

	source->ready = 0;
	switch_mutex_lock(globals.mutex);
	switch_core_hash_delete(globals.source_hash, source->name);
	switch_mutex_unlock(globals.mutex);

	switch_thread_rwlock_wrlock(source->rwlock);
	switch_thread_rwlock_unlock(source->rwlock);

	switch_buffer_destroy(&audio_buffer);

	if (fd > -1) {
		close(fd);
	}

	if (temp_pool) {
		switch_core_destroy_memory_pool(&temp_pool);
	}

	switch_core_destroy_memory_pool(&source->pool);

	switch_mutex_lock(globals.mutex);
	THREADS--;
	switch_mutex_unlock(globals.mutex);

	return NULL;
}
コード例 #9
0
vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile_name)
{
	vmivr_profile_t *profile = NULL;
	switch_xml_t cfg, xml, x_profiles, x_profile, x_apis, param;

	if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
		return profile;
	}
	if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
		goto end;
	}

	if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile_name))) {
		if (!(profile = switch_core_session_alloc(session, sizeof(vmivr_profile_t)))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n");
			goto end;	
		}

		profile->name = profile_name;

		/* TODO Make the following configurable */
		profile->api_profile = profile->name;
		profile->menu_check_auth = "std_authenticate";
		profile->menu_check_main = "std_navigator";
		profile->menu_check_terminate = "std_purge";

		if ((x_apis = switch_xml_child(x_profile, "apis"))) {
			int total_options = 0;
			int total_invalid_options = 0;
			for (param = switch_xml_child(x_apis, "api"); param; param = param->next) {
				char *var, *val;
				if ((var = (char *) switch_xml_attr_soft(param, "name")) && (val = (char *) switch_xml_attr_soft(param, "value"))) {
					if (!strcasecmp(var, "msg_undelete") && !profile->api_msg_undelete)
						profile->api_msg_undelete = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_delete") && !profile->api_msg_delete)
						profile->api_msg_delete = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_list") && !profile->api_msg_list)
						profile->api_msg_list = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_count") && !profile->api_msg_count)
						profile->api_msg_count = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_save") && !profile->api_msg_save)
						profile->api_msg_save = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_purge") && !profile->api_msg_purge)
						profile->api_msg_purge = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "msg_get") && !profile->api_msg_get)
						profile->api_msg_get = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "pref_greeting_set") && !profile->api_pref_greeting_set)
						profile->api_pref_greeting_set = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "pref_recname_set") && !profile->api_pref_recname_set)
						profile->api_pref_recname_set = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "pref_password_set") && !profile->api_pref_password_set)
						profile->api_pref_password_set = switch_core_session_strdup(session, val);
					else if (!strcasecmp(var, "auth_login") && !profile->api_auth_login)
						profile->api_auth_login = switch_core_session_strdup(session, val);
					else
						total_invalid_options++;
					total_options++;
				}
			}
			if (total_options - total_invalid_options != 11) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing api definition for profile '%s'\n", profile_name);
				profile = NULL;
			}
		}

	}

end:
	switch_xml_free(xml);
	return profile;
}
コード例 #10
0
ファイル: mod_sms.c プロジェクト: DastanIqbal/FreeSWITCH
static switch_event_t *chatplan_hunt(switch_event_t *event)
{
	switch_event_t *extension = NULL;
	switch_xml_t alt_root = NULL, cfg, xml = NULL, xcontext, xexten = NULL;
	const char *alt_path;
	const char *context;
	const char *from;
	const char *to;

	if (!(context = switch_event_get_header(event, "context"))) {
		context = "default";
	}

	if (!(from = switch_event_get_header(event, "from_user"))) {
		from = switch_event_get_header(event, "from");
	}

	if (!(to = switch_event_get_header(event, "to_user"))) {
		to = switch_event_get_header(event, "to");
	}

	alt_path = switch_event_get_header(event, "alt_path");

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Processing text message %s->%s in context %s\n", from, to, context);

	/* get our handle to the "chatplan" section of the config */

	if (!zstr(alt_path)) {
		switch_xml_t conf = NULL, tag = NULL;
		if (!(alt_root = switch_xml_parse_file_simple(alt_path))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of [%s] failed\n", alt_path);
			goto done;
		}

		if ((conf = switch_xml_find_child(alt_root, "section", "name", "chatplan")) && (tag = switch_xml_find_child(conf, "chatplan", NULL, NULL))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Getting chatplan from alternate path: %s\n", alt_path);
			xml = alt_root;
			cfg = tag;
		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n");
			goto done;
		}
	} else {
		if (switch_xml_locate("chatplan", NULL, NULL, NULL, &xml, &cfg, event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n");
			goto done;
		}
	}

	/* get a handle to the context tag */
	if (!(xcontext = switch_xml_find_child(cfg, "context", "name", context))) {
		if (!(xcontext = switch_xml_find_child(cfg, "context", "name", "global"))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Context %s not found\n", context);
			goto done;
		}
	}

	xexten = switch_xml_child(xcontext, "extension");
	
	while (xexten) {
		int proceed = 0;
		const char *cont = switch_xml_attr(xexten, "continue");
		const char *exten_name = switch_xml_attr(xexten, "name");

		if (!exten_name) {
			exten_name = "UNKNOWN";
		}

		switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG,
						  "Chatplan: %s parsing [%s->%s] continue=%s\n",
						  to, context, exten_name, cont ? cont : "false");

		proceed = parse_exten(event, xexten, &extension);
		
		if (proceed && !switch_true(cont)) {
			break;
		}

		xexten = xexten->next;
	}

	switch_xml_free(xml);
	xml = NULL;

  done:
	switch_xml_free(xml);
	return extension;
}
コード例 #11
0
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj)
{
	local_stream_source_t *source = obj;
	switch_file_handle_t fh = { 0 };
	local_stream_context_t *cp;
	char file_buf[128] = "", path_buf[512] = "", last_path[512], png_buf[512] = "", tmp_buf[512] = "";
	switch_timer_t timer = { 0 };
	int fd = -1;
	switch_buffer_t *audio_buffer;
	switch_byte_t *dist_buf;
	switch_size_t used;
	int skip = 0;
	switch_memory_pool_t *temp_pool = NULL;
	uint32_t dir_count = 0, do_shuffle = 0;
	char *p;

	switch_mutex_lock(globals.mutex);
	THREADS++;
	switch_mutex_unlock(globals.mutex);

	if (!source->prebuf) {
		source->prebuf = DEFAULT_PREBUFFER_SIZE;
	}

	if (source->shuffle) {
		do_shuffle = 1;
	}

	switch_queue_create(&source->video_q, 500, source->pool);
	switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0);
	dist_buf = switch_core_alloc(source->pool, source->prebuf + 10);

	switch_thread_rwlock_create(&source->rwlock, source->pool);

	if (RUNNING) {
		switch_mutex_lock(globals.mutex);
		switch_core_hash_insert(globals.source_hash, source->name, source);
		switch_mutex_unlock(globals.mutex);
		source->ready = 1;
	}

	while (RUNNING && !source->stopped) {
		const char *fname;

		if (temp_pool) {
			switch_core_destroy_memory_pool(&temp_pool);
		}

		if (switch_core_new_memory_pool(&temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error creating pool");
			goto done;
		}

		if (switch_dir_open(&source->dir_handle, source->location, temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't open directory: %s\n", source->location);
			goto done;
		}

		if (fd > -1) {
			dir_count = 0;
			while (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
				dir_count++;
			}
			lseek(fd, 0, SEEK_SET);
		} else {
			dir_count = switch_dir_count(source->dir_handle);
		}

		if (do_shuffle) {
			skip = do_rand(dir_count);
			do_shuffle = 0;
		}

		switch_yield(1000000);

		while (RUNNING && !source->stopped) {
			switch_size_t olen;
			uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
			const char *artist = NULL, *title = NULL;

			if (fd > -1) {
				char *pb;
				if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
					if ((pb = strchr(path_buf, '\r')) || (pb = strchr(path_buf, '\n'))) {
						*pb = '\0';
					}
				} else {
					close(fd);
					fd = -1;
					continue;
				}
			} else {
				if (!(fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) {
					break;
				}

				switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname);

				if (switch_stristr(".loc", path_buf)) {
					if ((fd = open(path_buf, O_RDONLY)) < 0) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
						switch_yield(1000000);
					}
					continue;
				}
			}

			if (dir_count > 1 && !strcmp(last_path, path_buf)) {
				continue;
			}

			if (skip > 0) {
				skip--;
				continue;
			}

			switch_set_string(last_path, path_buf);

			fname = path_buf;
			fh.prebuf = source->prebuf;
			fh.pre_buffer_datalen = source->prebuf;

			if (switch_core_file_open(&fh,
									  (char *) fname,
									  source->channels, source->rate, SWITCH_FILE_FLAG_VIDEO | SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
				switch_yield(1000000);
				continue;
			}

			if (switch_core_file_has_video(&fh)) {
				flush_video_queue(source->video_q);
			}

			if (switch_core_timer_init(&timer, source->timer_name, source->interval, (int)source->samples, temp_pool) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
				switch_dir_close(source->dir_handle);
				source->dir_handle = NULL;
				goto done;
			}

			switch_img_free(&source->cover_art);
			switch_set_string(tmp_buf, path_buf);
			if ((p = strrchr(tmp_buf, '/'))) {
				*p++ = '\0';
				switch_snprintf(png_buf, sizeof(png_buf), "%s/art/%s.png", tmp_buf, p);				
				if (switch_file_exists(png_buf, source->pool) == SWITCH_STATUS_SUCCESS) {
					source->cover_art = switch_img_read_png(png_buf, SWITCH_IMG_FMT_I420);
				}
			}

			source->serno++;
			switch_safe_free(source->banner_txt);
			title = artist = NULL;
			
			switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, &artist);
			switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_TITLE, &title);
			
			if (title && (source->cover_art || switch_core_file_has_video(&fh))) {
				const char *format = "#cccccc:#333333:FreeSans.ttf:3%:";

				if (artist) {
					source->banner_txt = switch_mprintf("%s%s (%s)", format, title, artist);
				} else {
					source->banner_txt = switch_mprintf("%s%s", format, title);
				}
			}

			while (RUNNING && !source->stopped) {
				int is_open;
				switch_file_handle_t *use_fh = &fh;

				switch_core_timer_next(&timer);
				olen = source->samples;
				
				if (source->chime_total) {

					if (source->chime_counter > 0) {
						source->chime_counter -= (int32_t)source->samples;
					}

					if (!switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN) && source->chime_counter <= 0) {
						char *val;

						val = source->chime_list[source->chime_cur++];

						if (source->chime_cur >= source->chime_total) {
							source->chime_cur = 0;
						}

						if (switch_core_file_open(&source->chime_fh,
												  (char *) val,
												  source->channels,
												  source->rate, SWITCH_FILE_FLAG_VIDEO | SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", val);
						}


						if (switch_core_file_has_video(&source->chime_fh)) {
							flush_video_queue(source->video_q);
						}

					}

					if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
						use_fh = &source->chime_fh;
					}
				}

			retry:

				source->has_video = switch_core_file_has_video(use_fh) || source->cover_art || source->banner_txt;

				is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);

				if (source->hup) {
					source->hup = 0;
					if (is_open) {
						is_open = 0;

						switch_core_file_close(use_fh);
						flush_video_queue(source->video_q);
						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
							switch_core_file_close(&fh);
							use_fh = &fh;							
						}
						goto retry;
					}
				}
				
				if (is_open) {
					if (switch_core_has_video() && switch_core_file_has_video(use_fh)) {
						switch_frame_t vid_frame = { 0 };

						if (use_fh == &source->chime_fh && switch_core_file_has_video(&fh)) {
							if (switch_core_file_read_video(&fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
								switch_img_free(&vid_frame.img);
							}
						}

						if (switch_core_file_read_video(use_fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
							if (vid_frame.img) {
								int flush = 1;

								source->has_video = 1;
								
								if (source->total) {
									if (switch_queue_trypush(source->video_q, vid_frame.img) == SWITCH_STATUS_SUCCESS) {
										flush = 0;
									}
								}

								if (flush) {
									switch_img_free(&vid_frame.img);
									flush_video_queue(source->video_q);
								}
							}
						}
					} else {
						source->has_video = 0;
					}

					if (use_fh == &source->chime_fh) {
						olen = source->samples;
						switch_core_file_read(&fh, abuf, &olen);
						olen = source->samples;
					}

					if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
						switch_core_file_close(use_fh);
						flush_video_queue(source->video_q);

						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
							use_fh = &fh;
						} else {
							is_open = 0;
						}
					} else {
						if (use_fh == &source->chime_fh && source->chime_max) {
							source->chime_max_counter += (int32_t)source->samples;
							if (source->chime_max_counter >= source->chime_max) {
								source->chime_max_counter = 0;
								switch_core_file_close(use_fh);
								flush_video_queue(source->video_q);
								source->chime_counter = source->rate * source->chime_freq;
								use_fh = &fh;
								goto retry;
							}
						}
						
						if (source->total) {
							switch_buffer_write(audio_buffer, abuf, olen * 2 * source->channels);
						} else {
							switch_buffer_zero(audio_buffer);
						}
					}
				}

				used = switch_buffer_inuse(audio_buffer);

				if (!used && !is_open) {
					break;
				}

				if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
					void *pop;

					used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);

					if (!source->total) {
						flush_video_queue(source->video_q);
					} else {
						uint32_t bused = 0;

						switch_mutex_lock(source->mutex);
						for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
							
							if (source->has_video) {
								switch_set_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
							} else {
								switch_clear_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
							}
							
							if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
								continue;
							}
							
							switch_mutex_lock(cp->audio_mutex);
							bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer);
							if (bused > source->samples * 768) {
								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", 
												  cp->func, cp->file, cp->line, bused, (long)source->samples);
								switch_buffer_zero(cp->audio_buffer);
							} else {
								switch_buffer_write(cp->audio_buffer, dist_buf, used);
							}
							switch_mutex_unlock(cp->audio_mutex);
						}
						switch_mutex_unlock(source->mutex);

						
						while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
							switch_image_t *img = (switch_image_t *) pop;
							switch_image_t *imgcp = NULL;

							if (source->total == 1) {
								switch_queue_push(source->context_list->video_q, img);
							} else {
								if (source->context_list) {
									switch_mutex_lock(source->mutex);
									for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
										if (cp->video_q) {
											imgcp = NULL;
											switch_img_copy(img, &imgcp);
											if (imgcp) {
												if (switch_queue_trypush(cp->video_q, imgcp) != SWITCH_STATUS_SUCCESS) {
													flush_video_queue(cp->video_q);
												}
											}
										}
									}
									switch_mutex_unlock(source->mutex);
								}
								switch_img_free(&img);
							}
						}
					}
				}
			}

			switch_core_timer_destroy(&timer);
			if (RUNNING && source->shuffle) {
				skip = do_rand(dir_count);
			}
		}

		switch_dir_close(source->dir_handle);
		source->dir_handle = NULL;

		if (source->full_reload) {
			if (source->rwlock && switch_thread_rwlock_trywrlock(source->rwlock) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot stop local_stream://%s because it is in use.\n",source->name);
				if (source->part_reload) {
					switch_xml_t cfg, xml, directory, param;
					if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
					}
					if ((directory = switch_xml_find_child(cfg, "directory", "name", source->name))) {
						for (param = switch_xml_child(directory, "param"); param; param = param->next) {
							char *var = (char *) switch_xml_attr_soft(param, "name");
							char *val = (char *) switch_xml_attr_soft(param, "value");
							if (!strcasecmp(var, "shuffle")) {
								source->shuffle = switch_true(val);
							} else if (!strcasecmp(var, "chime-freq")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_freq = tmp;
								}
							} else if (!strcasecmp(var, "chime-max")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_max = tmp;
								}
							} else if (!strcasecmp(var, "chime-list")) {
								char *list_dup = switch_core_strdup(source->pool, val);
								source->chime_total =
									switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0])));
							} else if (!strcasecmp(var, "interval")) {
								int tmp = atoi(val);
								if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
									source->interval = tmp;
								} else {
									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
													  "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
								}
							}
							if (source->chime_max) {
								source->chime_max *= source->rate;
							}
							if (source->chime_total) {
								source->chime_counter = source->rate * source->chime_freq;
							}
						}
					}
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name);
					source->part_reload = 0;
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name);
				launch_streams(source->name);
				goto done;
			}
		}
	}

  done:

	switch_safe_free(source->banner_txt);
	
	if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&fh);
	}

	if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&source->chime_fh);
	}

	source->ready = 0;
	switch_mutex_lock(globals.mutex);
	switch_core_hash_delete(globals.source_hash, source->name);
	switch_mutex_unlock(globals.mutex);

	switch_thread_rwlock_wrlock(source->rwlock);
	switch_thread_rwlock_unlock(source->rwlock);

	switch_buffer_destroy(&audio_buffer);

	flush_video_queue(source->video_q);

	if (fd > -1) {
		close(fd);
	}

	if (temp_pool) {
		switch_core_destroy_memory_pool(&temp_pool);
	}

	switch_core_destroy_memory_pool(&source->pool);

	switch_mutex_lock(globals.mutex);
	THREADS--;
	switch_mutex_unlock(globals.mutex);

	return NULL;
}
コード例 #12
0
switch_status_t load_agent(const char *agent_name)
{
	switch_xml_t x_agents, x_agent, cfg, xml;

	if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
		return SWITCH_STATUS_FALSE;
	}
	if (!(x_agents = switch_xml_child(cfg, "agents"))) {
		goto end;
	}

	if ((x_agent = switch_xml_find_child(x_agents, "agent", "name", agent_name))) {
		const char *type = switch_xml_attr(x_agent, "type");
		const char *contact = switch_xml_attr(x_agent, "contact"); 
		const char *status = switch_xml_attr(x_agent, "status");
		const char *max_no_answer = switch_xml_attr(x_agent, "max-no-answer");
		const char *wrap_up_time = switch_xml_attr(x_agent, "wrap-up-time");
		const char *reject_delay_time = switch_xml_attr(x_agent, "reject-delay-time");
		const char *busy_delay_time = switch_xml_attr(x_agent, "busy-delay-time");
		const char *no_answer_delay_time = switch_xml_attr(x_agent, "no-answer-delay-time");

		if (type) {
			cc_status_t res = cc_agent_add(agent_name, type);
			
            // For HA, only add new agent, DO NOT update or DELETE.
            if (res == CC_STATUS_AGENT_ALREADY_EXIST) {
                goto end;
            }
            
            if (res == CC_STATUS_SUCCESS) {
				if (contact) {
					cc_agent_update("contact", contact, agent_name);
				}
				if (status) {
					cc_agent_update("status", status, agent_name);
				}
				if (wrap_up_time) {
					cc_agent_update("wrap_up_time", wrap_up_time, agent_name);
				}
				if (max_no_answer) {
					cc_agent_update("max_no_answer", max_no_answer, agent_name);
				}
				if (reject_delay_time) {
					cc_agent_update("reject_delay_time", reject_delay_time, agent_name);
				}
				if (busy_delay_time) {
					cc_agent_update("busy_delay_time", busy_delay_time, agent_name);
				}
				if (no_answer_delay_time) {
					cc_agent_update("no_answer_delay_time", no_answer_delay_time, agent_name);
				}
				/*
                if (type && res == CC_STATUS_AGENT_ALREADY_EXIST) {
					cc_agent_update("type", type, agent_name);
				}*/

			}
		}
	}

end:

	if (xml) {
		switch_xml_free(xml);
	}

	return SWITCH_STATUS_SUCCESS;
}