/* ** internal_dispatch.c ** $Id: internal_dispatch.c,v 1.13 2002/09/19 06:13:21 brian Exp $ */ #include "mod_mp3.h" #include "internal_dispatch.h" mp3_data * internal_random(internal_context *context, pool *p) { mp3_data **banks = (mp3_data **)context->files->elts; int x = 0; /* for better PRNG seeding with microseconds versus current seconds */ struct timeval tv_struct[2]; gettimeofday(tv_struct, 0); srandom (tv_struct[0].tv_sec % tv_struct[0].tv_usec); if (context->each_counter == context->files->nelts) { context->each_counter = 0; memset(context->seen, 0, sizeof(int) * context->files->nelts); return NULL; } else { context->each_counter++; } for(;;) { x = ((int)random() % context->files->nelts); if(context->seen[x]) { continue; } else { context->seen[x] = 1; } return banks[x]; } } MP3_EXPORT(void *) internal_create(pool *p) { internal_context *context = ap_pcalloc(p, sizeof(internal_context)); context->each_counter = 0; context->seen = NULL; context->files = ap_make_array (p, DEFAULT_FILES, sizeof (mp3_data *)); return context; } MP3_EXPORT(int) internal_request(void *info, void *passcfg, pool *p) { internal_context *context = (internal_context *)info; context->each_counter = 0; context->seen = ap_pcalloc(p, context->files->nelts * sizeof(int)); memset(context->seen, 0, sizeof(int) * context->files->nelts); return 0; } MP3_EXPORT(mp3_data *) internal_get(void *info, pool *p, char *filename) { internal_context *context = (internal_context *)info; mp3_data **files = NULL; int x = 0; files = (mp3_data **)context->files->elts; for(x = 0; x < context->files->nelts; x++) { if(!strcmp(files[x]->signature, filename)) { return files[x]; } } return NULL; } MP3_EXPORT(int) internal_set(void *info, pool *p, mp3_data *file) { internal_context *context = (internal_context *)info; *(mp3_data **) ap_push_array (context->files) = (mp3_data *) file; return 0; } MP3_EXPORT(mp3_data *) internal_each(void *info, pool *p, array_header *files, const char *token, int random) { internal_context *context = (internal_context *)info; mp3_data **banks = (mp3_data **)context->files->elts; char **files_fetch = NULL; int x = 0; if (random) { return internal_random(context, p); } if(files) { files_fetch = (char **)files->elts; banks = (mp3_data **)context->files->elts; if (context->each_counter == files->nelts) { context->each_counter = 0; return NULL; } for(x = 0; x < context->files->nelts; x++) { if(!strcmp(banks[x]->signature, files_fetch[context->each_counter])) { context->each_counter++; return banks[x]; } } #ifdef DEAD_CODE /* No token support at this time, if you write it, put it here */ } else if (token) { #endif } else { if (context->each_counter == context->files->nelts) { context->each_counter = 0; return NULL; } context->each_counter++; } return banks[context->each_counter -1]; } MP3_EXPORT(int) internal_count(void *info, pool *p, array_header *files, const char *token) { internal_context *context = (internal_context *)info; int count = 0; if(files) { /* This is technically wrong, we should check to make sure we have matches */ count = files->nelts; } else { count = context->files->nelts; } return count; } MP3_EXPORT(array_header *) internal_search(void *info, pool *p, const char *pattern, int limit) { internal_context *context = (internal_context *)info; array_header *signatures = NULL; mp3_data **files = NULL; int x = 0; int max = (limit ? limit : context->files->nelts); files = (mp3_data **)context->files->elts; if(pattern) { for(x = 0; x < context->files->nelts; x++) { if(!mp3_match(pattern, files[x]->name)) { /* Create the array if we need to */ if(!signatures) signatures = ap_make_array(p, SEARCH_PRIME, sizeof (mp3_data *)); *(char **) ap_push_array (signatures) = ap_pstrdup (p, files[x]->signature); } } } else { /* Kinda stupid isn't it? */ signatures = ap_make_array(p, max, sizeof (char *)); for(x = 0; x < max; x++) { *(char **) ap_push_array (signatures) = ap_pstrdup (p, files[x]->signature); } } return signatures; } mp3_dispatch internal = { "internal", /* Name of the dispatch */ internal_create, /* Create a context */ NULL, /* Init to run when server forks for child */ internal_request, /* Init to run when request is made */ internal_get, /* Get request */ internal_set, /* Set an item request */ internal_each, /* Each operator to run through entire list */ internal_count, /* Method to count available files */ internal_search, /* This returns filenames based on a pattern, if no pattern is give then it should return all signatures in the system.*/ };