/* * Copyright (C) 2004-2007 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ /** \file random_selector.c An audio file selector which chooses files by random */ #include /* gettimeofday */ #include "server.cmdline.h" #include "server.h" #include "afs_common.h" #include "error.h" #include "net.h" #include "string.h" #include "random_selector_command_list.h" extern struct misc_meta_data *mmd; static unsigned int num_audio_files, audio_file_count; static char **audio_file_list; static int count_audio_files(__a_unused const char *dir, __a_unused const char *name) { num_audio_files++; return 1; } static int remember_file(const char *dir, const char *name) { if (audio_file_count < num_audio_files) { audio_file_list[audio_file_count] = make_message("%s/%s", dir, name); audio_file_count++; } return 1; } int com_random_info(int fd, __a_unused int argc, __a_unused char *argv[]) { return send_buffer(fd, "Don't use for huge directories as it is " "very inefficient in this case.\n"); } /* * Load a list of all audio files into memory and chose num of them randomly. * Called by server to determine next audio file to be streamed. */ static char **random_get_audio_file_list(unsigned int num) { int i, ret; unsigned int len; char **ret_list = NULL; /* what we are going to return */ audio_file_list = NULL; num_audio_files = 0; /* first run, just count all audio files. dopey */ ret = find_audio_files(conf.random_dir_arg, count_audio_files); if (ret < 0) goto out; ret = -E_NOTHING_FOUND; if (!num_audio_files) goto out; /* yeah, that doesn't scale, also dopey */ audio_file_list = para_malloc(num_audio_files * sizeof(char *)); audio_file_count = 0; /* second run (hot dentry cache, hopefully), fill audio_file_list */ ret = find_audio_files(conf.random_dir_arg, remember_file); if (ret < 0) goto out; /* careful, files might got deleted underneath */ num_audio_files = audio_file_count; /* can only decrease */ len = PARA_MIN(num, num_audio_files); ret = -E_NOTHING_FOUND; if (!len) /* nothing found, return NULL */ goto out; /* success, return NULL-terminated list */ ret_list = para_calloc((len + 1) * sizeof(char *)); for (i = 0; i < len; i++) { /* choose randomly */ int r = (int) ((num_audio_files + 0.0) * (rand() / (RAND_MAX + 1.0))); ret_list[i] = para_strdup(audio_file_list[r]); } ret = 1; out: if (audio_file_list) { for (i = 0; i < num_audio_files; i++) free(audio_file_list[i]); free(audio_file_list); } if (ret > 0) { } else sprintf(mmd->selector_info, "dbinfo1:%s\n", PARA_STRERROR(-ret)); return ret_list; } static void random_update_audio_file(char *audio_file) { char *dn = para_dirname(audio_file); snprintf(mmd->selector_info, MMD_INFO_SIZE - 1, "dbinfo1:current dir: %s\n" "dbinfo2:random_dir: %s\n" "dbinfo3:%d files available\n", dn, conf.random_dir_arg, num_audio_files); free(dn); mmd->selector_info[MMD_INFO_SIZE - 1] = '\0'; } static void random_shutdown(void) { } /** * the init function for the random audio file selector * * \param s pointer ro the struct to iniitalize * * Init all function pointers of \a s, init the info text and seed the PRNG. * * \sa struct audio_file_selector, misc_meta_data::selector_info, mysql.c */ int random_selector_init(struct audio_file_selector *s) { struct timeval now; unsigned int seed; PARA_INFO_LOG("%s", "registering random handlers ;)\n"); gettimeofday(&now, NULL); seed = now.tv_usec; srand(seed); s->cmd_list = random_selector_cmds; s->get_audio_file_list = random_get_audio_file_list; s->shutdown = random_shutdown; s->update_audio_file = random_update_audio_file; snprintf(mmd->selector_info, MMD_INFO_SIZE - 1, "dbinfo1: Welcome to the random selector\n" "dbinfo2: random_dir: %s\n", conf.random_dir_arg); mmd->selector_info[MMD_INFO_SIZE - 1] = '\0'; return 1; }