Order_list* new_Order_list(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; // Create the base structure Order_list* ol = memory_alloc_item(Order_list); if (ol == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); return NULL; } ol->pat_insts = NULL; ol->index_map = NULL; // Create Pattern instance reference vector ol->pat_insts = new_Vector(sizeof(Pat_inst_ref)); if (ol->pat_insts == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); del_Order_list(ol); return NULL; } // Create reverse index of ol->pat_insts ol->index_map = new_AAtree( (AAtree_item_cmp*)Pat_inst_ref_cmp, (AAtree_item_destroy*)memory_free); if (ol->index_map == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); del_Order_list(ol); return NULL; } // List is empty by default if (!Streader_has_data(sr)) return ol; // Read the list of Pattern instance references if (!Streader_read_list(sr, read_piref, ol)) { del_Order_list(ol); return NULL; } return ol; }
Note_map* new_Note_map_from_string(Streader* sr) { assert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; Note_map* map = memory_alloc_item(Note_map); if (map == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for note map"); return NULL; } map->map = NULL; map->iter = NULL; map->map = new_AAtree( (int (*)(const void*, const void*))Random_list_cmp, (void (*)(void*))del_Random_list); if (map->map == NULL) { del_Note_map(map); Streader_set_memory_error( sr, "Could not allocate memory for note map"); return NULL; } map->iter = new_AAiter(map->map); if (map->iter == NULL) { del_Note_map(map); Streader_set_memory_error( sr, "Could not allocate memory for note map"); return NULL; } if (!Streader_has_data(sr)) return map; if (!Streader_read_list(sr, read_mapping, map)) { del_Note_map(map); return NULL; } return map; }
Channel_defaults_list* new_Channel_defaults_list(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; Channel_defaults_list* cdl = memory_alloc_item(Channel_defaults_list); if (cdl == NULL) { Streader_set_memory_error(sr, "Could not allocate memory for channel defaults"); return NULL; } for (int ch = 0; ch < KQT_CHANNELS_MAX; ++ch) Channel_defaults_init(&cdl->ch_defaults[ch]); if (!Streader_has_data(sr)) return cdl; if (!Streader_read_list(sr, read_ch_defaults_item, cdl)) { del_Channel_defaults_list(cdl); return NULL; } return cdl; }
static bool read_env_var(Streader* sr, int32_t index, void* userdata) { assert(sr != NULL); (void)index; assert(userdata != NULL); AAtree* new_vars = userdata; Env_var* var = new_Env_var_from_string(sr); if (var == NULL) return false; if (AAtree_contains(new_vars, Env_var_get_name(var))) { Streader_set_error( sr, "Variable name %s is not unique", Env_var_get_name(var)); del_Env_var(var); return false; } if (!AAtree_ins(new_vars, var)) { Streader_set_memory_error( sr, "Could not allocate memory for environment"); del_Env_var(var); return false; } return true; }
Hit_map* new_Hit_map_from_string(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; Hit_map* map = memory_alloc_item(Hit_map); if (map == NULL) { Streader_set_memory_error(sr, "Could not allocate memory for hit map"); return NULL; } for (int i = 0; i < KQT_HITS_MAX; ++i) map->hits[i] = NULL; if (!Streader_has_data(sr)) return map; if (!Streader_read_list(sr, read_mapping, map)) { del_Hit_map(map); return NULL; } return map; }
Au_expressions* new_Au_expressions(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; Au_expressions* ae = memory_alloc_item(Au_expressions); if (ae == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for audio unit expressions"); return NULL; } memset(ae->default_note_expr, '\0', KQT_VAR_NAME_MAX); ae->entries = new_AAtree( (AAtree_item_cmp*)strcmp, (AAtree_item_destroy*)del_Entry); if (ae->entries == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for audio unit expressions"); del_Au_expressions(ae); return NULL; } if (!Streader_read_dict(sr, read_expressions_def, ae)) { rassert(Streader_is_error_set(sr)); del_Au_expressions(ae); return NULL; } if (ae->default_note_expr[0] != '\0' && !Au_expressions_get_proc_filter(ae, ae->default_note_expr)) { Streader_set_error( sr, "Audio unit expressions do not contain the default expression %s", ae->default_note_expr); del_Au_expressions(ae); return NULL; } return ae; }
static bool read_piref(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); rassert(userdata != NULL); Order_list* ol = userdata; // Read the Pattern instance reference Pat_inst_ref* p = PAT_INST_REF_AUTO; if (!Streader_read_piref(sr, p)) return false; // Check if the Pattern instance is already used Index_mapping* key = INDEX_MAPPING_AUTO; key->p = *p; key->ol_index = index; if (AAtree_contains(ol->index_map, key)) { Streader_set_error( sr, "Duplicate occurrence of pattern instance" " [%" PRId16 ", %" PRId16 "]", p->pat, p->inst); return false; } // Add the reference to our containers if (!Vector_append(ol->pat_insts, p)) { Streader_set_memory_error( sr, "Could not allocate memory for order list"); return false; } Index_mapping* im = new_Index_mapping(key); if (im == NULL || !AAtree_ins(ol->index_map, im)) { memory_free(im); Streader_set_memory_error( sr, "Could not allocate memory for order list"); return false; } return true; }
Connections* new_Connections_from_string( Streader* sr, Connection_level level, Au_table* au_table, Device* master) { rassert(sr != NULL); rassert(au_table != NULL); rassert(master != NULL); if (Streader_is_error_set(sr)) return NULL; Connections* graph = memory_alloc_item(Connections); if (graph == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for connections"); return NULL; } graph->nodes = NULL; graph->nodes = new_AAtree( (int (*)(const void*, const void*))Device_node_cmp, (void (*)(void*))del_Device_node); mem_error_if(graph->nodes == NULL, graph, NULL, sr); Device_node* master_node = NULL; if (level == CONNECTION_LEVEL_AU) { const Device* iface = Audio_unit_get_output_interface((Audio_unit*)master); master_node = new_Device_node("", au_table, iface); } else { master_node = new_Device_node("", au_table, master); } mem_error_if(master_node == NULL, graph, NULL, sr); mem_error_if(!AAtree_ins(graph->nodes, master_node), graph, master_node, sr); if (!Streader_has_data(sr)) return graph; read_conn_data rcdata = { graph, level, au_table, master }; if (!Streader_read_list(sr, read_connection, &rcdata)) { del_Connections(graph); return NULL; } if (Connections_is_cyclic(graph)) { Streader_set_error(sr, "The connection graph contains a cycle"); del_Connections(graph); return NULL; } return graph; }
Tuning_table* new_Tuning_table_from_string(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; Tuning_table* tt = new_Tuning_table( TUNING_TABLE_DEFAULT_REF_PITCH, TUNING_TABLE_DEFAULT_OCTAVE_WIDTH); if (tt == NULL) { Streader_set_memory_error( sr, "Couldn't allocate memory for tuning table"); return NULL; } if (Streader_has_data(sr)) { if (!Streader_read_dict(sr, read_tuning_table_item, tt)) { del_Tuning_table(tt); return NULL; } if (tt->ref_note >= tt->note_count) { Streader_set_error(sr, "Reference note doesn't exist: %d", tt->ref_note); del_Tuning_table(tt); return NULL; } } if (!Tuning_table_build_pitch_map(tt)) { Streader_set_memory_error(sr, "Couldn't allocate memory for tuning table"); del_Tuning_table(tt); return NULL; } return tt; }
Num_list* new_Num_list_from_string(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; if (!Streader_has_data(sr)) return NULL; Num_list* nl = memory_alloc_item(Num_list); if (nl == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for number list"); return NULL; } nl->len = 0; nl->res = 8; nl->nums = NULL; nl->nums = memory_alloc_items(double, nl->res); if (nl->nums == NULL) { del_Num_list(nl); Streader_set_memory_error( sr, "Could not allocate memory for number list"); return NULL; } if (!Streader_read_list(sr, read_num, nl)) { del_Num_list(nl); return NULL; } return nl; }
bool Device_set_key(Device* device, const char* key, Streader* sr) { assert(device != NULL); assert(key != NULL); assert(string_has_prefix(key, "i/") || string_has_prefix(key, "c/")); assert(sr != NULL); if (Streader_is_error_set(sr)) return false; if (!Device_params_parse_value(device->dparams, key, sr)) return false; if (device->dimpl != NULL && !Device_impl_set_key(device->dimpl, key + 2)) { Streader_set_memory_error( sr, "Could not allocate memory for device key %s", key); return false; } return true; }
static bool read_num(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); ignore(index); rassert(userdata != NULL); Num_list* nl = userdata; double num = NAN; if (!Streader_read_float(sr, &num)) return false; if (!Num_list_append(nl, num)) { del_Num_list(nl); Streader_set_memory_error( sr, "Could not allocate memory for number list"); return false; } return true; }
bool Environment_parse(Environment* env, Streader* sr) { assert(env != NULL); assert(sr != NULL); if (Streader_is_error_set(sr)) return false; if (!Streader_has_data(sr)) { AAtree_clear(env->vars); AAiter_change_tree(env->iter, env->vars); return true; } AAtree* new_vars = new_AAtree( (int (*)(const void*, const void*))strcmp, (void (*)(void*))del_Env_var); if (new_vars == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for environment"); return false; } if (!Streader_read_list(sr, read_env_var, new_vars)) { del_AAtree(new_vars); return false; } AAiter_change_tree(env->iter, new_vars); AAtree* old_vars = env->vars; env->vars = new_vars; del_AAtree(old_vars); return true; }
Env_var* new_Env_var_from_string(Streader* sr) { rassert(sr != NULL); if (Streader_is_error_set(sr)) return NULL; char type_name[16] = ""; char name[KQT_VAR_NAME_MAX] = ""; if (!Streader_readf( sr, "[%s,%s,", READF_STR(16, type_name), READF_STR(KQT_VAR_NAME_MAX, name))) return NULL; if (!is_valid_var_name(name)) { Streader_set_error( sr, "Illegal variable name %s" " (Variable names may only contain" " lower-case letters and underscores" " (and digits as other than first characters))", name); return NULL; } Value* value = VALUE_AUTO; if (string_eq(type_name, "bool")) { value->type = VALUE_TYPE_BOOL; Streader_read_bool(sr, &value->value.bool_type); } else if (string_eq(type_name, "int")) { value->type = VALUE_TYPE_INT; Streader_read_int(sr, &value->value.int_type); } else if (string_eq(type_name, "float")) { value->type = VALUE_TYPE_FLOAT; Streader_read_float(sr, &value->value.float_type); } else if (string_eq(type_name, "timestamp")) { value->type = VALUE_TYPE_TSTAMP; Streader_read_tstamp(sr, &value->value.Tstamp_type); } else { Streader_set_error( sr, "Invalid type of environment variable %s: %s", name, type_name); return NULL; } if (!Streader_match_char(sr, ']')) return NULL; Env_var* var = new_Env_var(value->type, name); if (var == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for environment variable"); return NULL; } Env_var_set_value(var, value); return var; }
static bool read_mapping(Streader* sr, int32_t index, void* userdata) { assert(sr != NULL); (void)index; assert(userdata != NULL); Note_map* map = userdata; Random_list* list = memory_alloc_item(Random_list); if (list == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for note map entry"); return false; } double cents = NAN; double force = NAN; if (!Streader_readf(sr, "[[%f,%f],", ¢s, &force)) { memory_free(list); return false; } if (!isfinite(cents)) { Streader_set_error(sr, "Mapping cents is not finite"); memory_free(list); return false; } if (!isfinite(force)) { Streader_set_error(sr, "Mapping force is not finite"); memory_free(list); return false; } list->freq = exp2(cents / 1200) * 440; list->cents = cents; list->force = force; list->entry_count = 0; if (!AAtree_ins(map->map, list)) { Streader_set_memory_error( sr, "Couldn't allocate memory for note map entry"); memory_free(list); return false; } if (!Streader_read_list(sr, read_random_list_entry, list)) return false; if (list->entry_count == 0) { Streader_set_error(sr, "Empty note mapping random list"); return false; } return Streader_match_char(sr, ']'); }
static bool read_mapping(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); ignore(index); rassert(userdata != NULL); Hit_map* map = userdata; Random_list* list = memory_alloc_item(Random_list); if (list == NULL) { del_Hit_map(map); Streader_set_memory_error( sr, "Could not allocate memory for hit map random list"); return false; } int64_t hit_index = -1; double force = NAN; if (!Streader_readf(sr, "[[%i,%f],", &hit_index, &force)) { memory_free(list); return false; } if (hit_index < 0 || hit_index >= KQT_HITS_MAX) { Streader_set_error( sr, "Mapping hit index is outside range [0, %d)", KQT_HITS_MAX); memory_free(list); return false; } if (!isfinite(force)) { Streader_set_error( sr, "Mapping force is not finite", KQT_HITS_MAX); memory_free(list); return false; } if (map->hits[hit_index] == NULL) { map->hits[hit_index] = new_AAtree( (AAtree_item_cmp*)Random_list_cmp, (AAtree_item_destroy*)memory_free); if (map->hits[hit_index] == NULL) { Streader_set_memory_error( sr, "Could not allocate memory for hit map"); memory_free(list); return false; } } list->force = force; list->entry_count = 0; if (AAtree_contains(map->hits[hit_index], list)) { Streader_set_error( sr, "Duplicate hit map entry with hit index %" PRId64 ", force %.2f", hit_index, force); memory_free(list); return false; } if (!AAtree_ins(map->hits[hit_index], list)) { Streader_set_memory_error( sr, "Could not allocate memory for hit map random list"); memory_free(list); return false; } if (!Streader_read_list(sr, read_random_list_entry, list)) return false; return Streader_match_char(sr, ']'); }