[svn-commits] dlee: branch dlee/record r394822 - /team/dlee/record/res/stasis_recording/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jul 19 16:23:14 CDT 2013


Author: dlee
Date: Fri Jul 19 16:23:12 2013
New Revision: 394822

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=394822
Log:
It works. I guess.

Modified:
    team/dlee/record/res/stasis_recording/stored.c

Modified: team/dlee/record/res/stasis_recording/stored.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/res/stasis_recording/stored.c?view=diff&rev=394822&r1=394821&r2=394822
==============================================================================
--- team/dlee/record/res/stasis_recording/stored.c (original)
+++ team/dlee/record/res/stasis_recording/stored.c Fri Jul 19 16:23:12 2013
@@ -43,7 +43,7 @@
 		AST_STRING_FIELD(file_with_ext);	/*!< Absolute filename, with extension; for use with everything  */
 		);
 
-	const char *format;	/*!< Format name (i.e. filename extension) */
+	char *format;	/*!< Format name (i.e. filename extension) */
 };
 
 static void stored_recording_dtor(void *obj)
@@ -113,7 +113,7 @@
 	char *file_with_ext = NULL;
 
 	dir = opendir(dir_name);
-	if (dir == NULL) {
+	if (!dir) {
 		return NULL;
 	}
 
@@ -216,9 +216,171 @@
 		"format", recording->format);
 }
 
+static int recording_sort(const void *obj_left, const void *obj_right, int flags)
+{
+	const struct stasis_app_stored_recording *object_left = obj_left;
+	const struct stasis_app_stored_recording *object_right = obj_right;
+	const char *right_key = obj_right;
+	int cmp;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	case OBJ_POINTER:
+		right_key = object_right->name;
+		/* Fall through */
+	case OBJ_KEY:
+		cmp = strcmp(object_left->name, right_key);
+		break;
+	case OBJ_PARTIAL_KEY:
+		/*
+		 * We could also use a partial key struct containing a length
+		 * so strlen() does not get called for every comparison instead.
+		 */
+		cmp = strncmp(object_left->name, right_key, strlen(right_key));
+		break;
+	default:
+		/* Sort can only work on something with a full or partial key. */
+		ast_assert(0);
+		cmp = 0;
+		break;
+	}
+	return cmp;
+}
+
+static int find_all_in_dir(struct ao2_container *recordings,
+	const char *base_dir, const char *dir_name)
+{
+	RAII_VAR(char *, full_dir, NULL, ast_free);
+	RAII_VAR(DIR *, dir, NULL, closedir);
+	struct dirent entry = {};
+	struct dirent *result = NULL;
+
+	ast_verb(4, "Finding recordings in '%s'\n", dir_name);
+
+	if (ast_strlen_zero(dir_name)) {
+		full_dir = ast_strdup(base_dir);
+	} else {
+		ast_asprintf(&full_dir, "%s/%s", base_dir, dir_name);
+	}
+	if (!full_dir) {
+		ast_log(LOG_WARNING, "Error reading recording dir '%s'\n", dir_name);
+		return -1;
+	}
+
+	dir = opendir(full_dir);
+	if (!dir) {
+		ast_log(LOG_WARNING, "Error reading dir '%s'\n", full_dir);
+		return -1;
+	}
+
+	while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
+		RAII_VAR(struct stasis_app_stored_recording *, recording, NULL,
+			ao2_cleanup);
+		RAII_VAR(char *, file_with_ext, NULL, ast_free);
+		char *ext;
+		struct stat file_stat;
+		int res;
+
+		ast_verb(4, "Scanning '%s'\n", result->d_name);
+
+		if (strcmp(result->d_name, ".") == 0 ||
+			strcmp(result->d_name, "..") == 0) {
+			ast_verb(4, "  Ignore self/parent dir\n");
+			continue;
+		}
+
+		ast_asprintf(&file_with_ext, "%s/%s", full_dir, result->d_name);
+		if (!file_with_ext) {
+			ast_log(LOG_WARNING, "Error determining recording path\n");
+			continue;
+		}
+
+		res = stat(file_with_ext, &file_stat);
+		if (res != 0) {
+			ast_log(LOG_WARNING, "Error getting file info: %s\n", file_with_ext);
+			continue;
+		}
+
+		if (S_ISDIR(file_stat.st_mode)) {
+			/* process subdirectory */
+			RAII_VAR(char *, sub_dir, NULL, ast_free);
+
+			if (ast_strlen_zero(dir_name)) {
+				sub_dir = ast_strdup(result->d_name);
+			} else {
+				ast_asprintf(&sub_dir, "%s/%s", dir_name, result->d_name);
+			}
+			if (!sub_dir) {
+				ast_log(LOG_WARNING, "Error determining subdir path\n");
+				continue;
+
+			}
+			find_all_in_dir(recordings, base_dir, sub_dir);
+			continue;
+		}
+
+		if (!S_ISREG(file_stat.st_mode)) {
+			ast_log(LOG_WARNING,
+				"Skipping recording %s: not a regular file\n",
+				file_with_ext);
+			continue;
+		}
+
+		ext = strrchr(result->d_name, '.');
+
+		if (!ext) {
+			ast_verb(4, "  Ignore file without extension\n");
+			/* No file extension; not us */
+			continue;
+		}
+		++ext;
+
+		if (!ast_get_format_for_file_ext(ext)) {
+			ast_verb(4, "  Not a media file\n");
+			/* Not a media file */
+			continue;
+		}
+
+		recording = ao2_alloc(sizeof(*recording), stored_recording_dtor);
+		if (!recording) {
+			ast_log(LOG_WARNING, "Error allocating recording object for %s\n", file_with_ext);
+			continue;
+		}
+
+		ast_string_field_init(recording, 255);
+		ast_string_field_set(recording, file_with_ext, file_with_ext);
+
+		/* Build file and format from file_with_ext */
+		ast_string_field_set(recording, file, file_with_ext);
+		recording->format = strrchr(recording->file, '.');
+		*(recording->format++) = '\0';
+
+		/* Build name from file */
+		ast_string_field_set(recording, name,
+			recording->file + strlen(ast_config_AST_RECORDING_DIR) + 1);
+		ao2_link(recordings, recording);
+	}
+
+	return 0;
+}
+
 struct ao2_container *stasis_app_stored_recording_find_all(void)
 {
-	return NULL;
+	RAII_VAR(struct ao2_container *, recordings, NULL, ao2_cleanup);
+	int res;
+
+	recordings = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
+		AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, recording_sort, NULL);
+	if (!recordings) {
+		return NULL;
+	}
+
+	res = find_all_in_dir(recordings, ast_config_AST_RECORDING_DIR, "");
+	if (res != 0) {
+		return NULL;
+	}
+
+	ao2_ref(recordings, +1);
+	return recordings;
 }
 
 struct stasis_app_stored_recording *stasis_app_stored_recording_find_by_name(




More information about the svn-commits mailing list