📄 preset.c
字号:
/***************************************************************************** * preset.c: ***************************************************************************** * Copyright (C) 2004 VideoLAN * $Id: preset.c 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Cyril Deguet <asmax@videolan.org> * code from projectM http://xmms-projectm.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <dirent.h>#include <time.h>#include "common.h"#include "fatal.h"#include "preset_types.h"#include "preset.h"#include "parser.h"#include "expr_types.h"#include "eval.h"#include "splaytree_types.h"#include "splaytree.h"#include "tree_types.h"#include "per_frame_eqn_types.h"#include "per_frame_eqn.h"#include "per_pixel_eqn_types.h"#include "per_pixel_eqn.h"#include "init_cond_types.h"#include "init_cond.h"#include "param_types.h"#include "param.h"#include "func_types.h"#include "func.h"#include "custom_wave_types.h"#include "custom_wave.h"#include "custom_shape_types.h"#include "custom_shape.h"#include "idle_preset.h"/* The maximum number of preset names loaded into buffer */#define MAX_PRESETS_IN_DIR 50000extern int per_frame_eqn_count;extern int per_frame_init_eqn_count;//extern int custom_per_frame_eqn_count;extern splaytree_t * builtin_param_tree;preset_t * active_preset = NULL;preset_t * idle_preset = NULL;FILE * write_stream = NULL;int preset_index = -1;int preset_name_buffer_size = 0;splaytree_t * chrono_order_preset_name_tree = NULL;int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename);preset_t * load_preset(char * pathname);int is_valid_extension(char * name); int load_preset_file(char * pathname, preset_t * preset);int close_preset(preset_t * preset);int write_preset_name(FILE * fs);int write_per_pixel_equations(FILE * fs);int write_per_frame_equations(FILE * fs);int write_per_frame_init_equations(FILE * fs);int write_init_conditions(FILE * fs);void load_init_cond(param_t * param);void load_init_conditions();void write_init(init_cond_t * init_cond);int init_idle_preset();int destroy_idle_preset();void load_custom_wave_init_conditions();void load_custom_wave_init(custom_wave_t * custom_wave);void load_custom_shape_init_conditions();void load_custom_shape_init(custom_shape_t * custom_shape);/* loadPresetDir: opens the directory buffer denoted by 'dir' to load presets */ int loadPresetDir(char * dir) { struct dirent ** name_list; char * preset_name; int i, j, dir_size; if (dir == NULL) return ERROR; if (chrono_order_preset_name_tree != NULL) { if (PRESET_DEBUG) printf("loadPresetDir: previous directory doesn't appear to be closed!\n"); /* Let this slide for now */ } /* Scan the entire directory, storing each entry in a dirent struct array that needs to be freed later. For more information, consult scandir(3) in the man pages */ if ((dir_size = scandir(dir, &name_list, 0, alphasort)) < 0) { if (PRESET_DEBUG) printf("loadPresetDir: failed to open directory \"%s\"\n", dir); return ERROR; } chrono_order_preset_name_tree = create_splaytree(compare_int, copy_int, free_int); /* Iterate through entire dirent name list, adding to the preset name list if it is valid */ for (i = 0; ((i < dir_size) && (i < MAX_PRESETS_IN_DIR));i++) { /* Only perform the next set of operations if the preset name contains a valid extension */ if (is_valid_extension(name_list[i]->d_name)) { /* Handle the out of memory case. My guess is xmms would crash before this program would, but whatever...*/ if ((preset_name = (char*)malloc(MAX_PATH_SIZE)) == NULL) { if (PRESET_DEBUG) printf("loadPresetDir: out of memory! \n"); /* Free the rest of the dirent name list */ for (j = i; j < dir_size; j++) free(name_list[j]); destroy_splaytree(chrono_order_preset_name_tree); return OUTOFMEM_ERROR; } /* Now create the full path */ if (get_preset_path(&preset_name, dir, name_list[i]->d_name) < 0) { if (PRESET_DEBUG) printf("loadPresetDir: failed to generate full preset path name!\n"); /* Free the rest of the dirent name list */ for (j = i; j < dir_size; j++) free(name_list[j]); destroy_splaytree(chrono_order_preset_name_tree); return OUTOFMEM_ERROR; } /* Insert the character string into the splay tree, with the key being its sequence number */ splay_insert(preset_name, &preset_name_buffer_size, chrono_order_preset_name_tree); preset_name_buffer_size++; } /* Free the dirent struct */ free(name_list[i]); } free(name_list); /* No valid files in directory! */ if (chrono_order_preset_name_tree->root == NULL) { if (PRESET_DEBUG) printf("loadPresetDir: no valid files in directory \"%s\"\n", dir); destroy_splaytree(chrono_order_preset_name_tree); chrono_order_preset_name_tree = NULL; return FAILURE; } /* Start the prefix index right before the first entry, so next preset starts at the top of the list */ preset_index = -1; /* Start the first preset */ switchPreset(ALPHA_NEXT, HARD_CUT); return SUCCESS;}/* closePresetDir: closes the current preset directory buffer */int closePresetDir() { /* No preset director appears to be loaded */ if (chrono_order_preset_name_tree == NULL) return SUCCESS; if (PRESET_DEBUG) { printf("closePresetDir: freeing directory buffer..."); fflush(stdout); } /* Free each entry in the directory preset name tree */ splay_traverse(free_int, chrono_order_preset_name_tree); /* Destroy the chronological order splay tree */ destroy_splaytree(chrono_order_preset_name_tree); chrono_order_preset_name_tree = NULL; preset_name_buffer_size = 0; if (PRESET_DEBUG) printf("finished\n"); return SUCCESS;}/* Converts a preset file name to a full path */ int get_preset_path(char ** preset_path_ptr, char * filepath, char * filename) { char * preset_path; /* An insanely paranoid sequence of argument checks */ if (preset_path_ptr == NULL) return ERROR; if (*preset_path_ptr == NULL) return ERROR; if (filename == NULL) return ERROR; if (filepath == NULL) return ERROR; /* Mostly here for looks */ preset_path = *preset_path_ptr; /* Clear the name space first */ memset(preset_path, 0, MAX_PATH_SIZE); /* Now create the string "PATH/FILENAME", where path is either absolute or relative location of the .milk file, and filename is the name of the preset file itself */ strcat( strcat( strncpy( preset_path, filepath, MAX_PATH_SIZE-1), "/"), filename); return SUCCESS;} /* switchPreset: loads the next preset from the directory stream. loadPresetDir() must be called first. This is a sequential load function */int switchPreset(switch_mode_t switch_mode, int cut_type) { preset_t * new_preset; int switch_index; /* Make sure a preset directory list is in the buffer */ if (chrono_order_preset_name_tree == NULL) { if (PRESET_DEBUG) printf("switchPreset: it helps if you open a directory first with a loadPresetDir() call\n"); return ERROR; } switch (switch_mode) { case ALPHA_NEXT: /* An index variable that iterates through the directory buffer, doing wrap around when it reaches the end of the buffer */ if (preset_index == (preset_name_buffer_size - 1)) switch_index = preset_index = 0; else switch_index = ++preset_index; break; case ALPHA_PREVIOUS: if (preset_index == 0) switch_index = preset_index = preset_name_buffer_size - 1; else switch_index = --preset_index; break; case RANDOM_NEXT: switch_index = (int) (preset_name_buffer_size*(rand()/(RAND_MAX+1.0))); break; case RESTART_ACTIVE: switch_index = preset_index; break; default: return FAILURE; } /* Finally, load the preset using its actual path */ if ((new_preset = load_preset((char*)splay_find(&switch_index, chrono_order_preset_name_tree))) == NULL) { if (PRESET_DEBUG) printf("switchPreset: failed to load preset\n"); return ERROR; } /* Closes a preset currently loaded, if any */ if ((active_preset != NULL) && (active_preset != idle_preset)) close_preset(active_preset); /* Sets global active_preset pointer */ active_preset = new_preset; /* Reinitialize the engine variables to sane defaults */ reset_engine_vars(); /* Add any missing initial conditions */ load_init_conditions(); /* Add any missing initial conditions for each wave */ load_custom_wave_init_conditions();/* Add any missing initial conditions for each shape */ load_custom_shape_init_conditions(); /* Need to evaluate the initial conditions once */ evalInitConditions(); // evalInitPerFrameEquations(); return SUCCESS;}/* Loads a specific preset by absolute path */int loadPresetByFile(char * filename) { preset_t * new_preset; /* Finally, load the preset using its actual path */ if ((new_preset = load_preset(filename)) == NULL) { if (PRESET_DEBUG) printf("loadPresetByFile: failed to load preset!\n"); return ERROR; } /* Closes a preset currently loaded, if any */ if ((active_preset != NULL) && (active_preset != idle_preset)) close_preset(active_preset); /* Sets active preset global pointer */ active_preset = new_preset; /* Reinitialize engine variables */ reset_engine_vars(); /* Add any missing initial conditions for each wave */ load_custom_wave_init_conditions(); /* Add any missing initial conditions for each wave */ load_custom_shape_init_conditions(); /* Add any missing initial conditions */ load_init_conditions(); /* Need to do this once for menu */ evalInitConditions(); // evalPerFrameInitEquations(); return SUCCESS;}int init_idle_preset() { preset_t * preset; int i; /* Initialize idle preset struct */ if ((preset = (preset_t*)malloc(sizeof(preset_t))) == NULL) return FAILURE; strncpy(preset->name, "idlepreset", strlen("idlepreset")); /* Initialize equation trees */ preset->init_cond_tree = create_splaytree(compare_string, copy_string, free_string); preset->user_param_tree = create_splaytree(compare_string, copy_string, free_string); preset->per_frame_eqn_tree = create_splaytree(compare_int, copy_int, free_int); preset->per_pixel_eqn_tree = create_splaytree(compare_int, copy_int, free_int); preset->per_frame_init_eqn_tree = create_splaytree(compare_string, copy_string, free_string); preset->custom_wave_tree = create_splaytree(compare_int, copy_int, free_int); preset->custom_shape_tree = create_splaytree(compare_int, copy_int, free_int); /* Set file path to dummy name */ strncpy(preset->file_path, "IDLE PRESET", MAX_PATH_SIZE-1); /* Set initial index values */ preset->per_pixel_eqn_string_index = 0; preset->per_frame_eqn_string_index = 0; preset->per_frame_init_eqn_string_index = 0; memset(preset->per_pixel_flag, 0, sizeof(int)*NUM_OPS); /* Clear string buffers */ memset(preset->per_pixel_eqn_string_buffer, 0, STRING_BUFFER_SIZE); memset(preset->per_frame_eqn_string_buffer, 0, STRING_BUFFER_SIZE); memset(preset->per_frame_init_eqn_string_buffer, 0, STRING_BUFFER_SIZE); idle_preset = preset; return SUCCESS;}int destroy_idle_preset() { return close_preset(idle_preset); }/* initPresetLoader: initializes the preset loading library. this should be done before any parsing */int initPresetLoader() { /* Initializes the builtin parameter database */ init_builtin_param_db(); /* Initializes the builtin function database */ init_builtin_func_db(); /* Initializes all infix operators */ init_infix_ops(); /* Set the seed to the current time in seconds */ srand(time(NULL)); /* Initialize the 'idle' preset */ init_idle_preset(); reset_engine_vars(); active_preset = idle_preset; load_init_conditions(); /* Done */ if (PRESET_DEBUG) printf("initPresetLoader: finished\n"); return SUCCESS;}/* Sort of experimental code here. This switches to a hard coded preset. Useful if preset directory was not properly loaded, or a preset fails to parse */void switchToIdlePreset() { /* Idle Preset already activated */ if (active_preset == idle_preset) return; /* Close active preset */ if (active_preset != NULL) close_preset(active_preset); /* Sets global active_preset pointer */ active_preset = idle_preset; /* Reinitialize the engine variables to sane defaults */ reset_engine_vars(); /* Add any missing initial conditions */ load_init_conditions(); /* Need to evaluate the initial conditions once */ evalInitConditions();}/* destroyPresetLoader: closes the preset loading library. This should be done when projectM does cleanup */int destroyPresetLoader() { if ((active_preset != NULL) && (active_preset != idle_preset)) { close_preset(active_preset); } active_preset = NULL; destroy_idle_preset(); destroy_builtin_param_db(); destroy_builtin_func_db(); destroy_infix_ops(); return SUCCESS;}/* load_preset_file: private function that loads a specific preset denoted by the given pathname */int load_preset_file(char * pathname, preset_t * preset) { FILE * fs; int retval;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -