bool read_received_events(Streader* sr, int32_t index, void* userdata) { assert(sr != NULL); (void)index; assert(userdata != NULL); int32_t* expected = userdata; double actual = NAN; const char* event_name = (*expected % 16 == 0) ? "n+" : "vs"; if (!(Streader_readf(sr, "[0, [") && Streader_match_string(sr, event_name) && Streader_readf(sr, ", %f]]", &actual)) ) return false; if ((int)round(actual) != *expected) { Streader_set_error( sr, "Received argument %" PRId64 " instead of %" PRId32, actual, *expected); return false; } *expected = (int)round(actual) + 1; return true; }
END_TEST static bool test_reported_force(Streader* sr, double expected) { assert(sr != NULL); double actual = NAN; if (!(Streader_readf(sr, "[[0, [") && Streader_match_string(sr, "qf") && Streader_readf(sr, ", null]], [0, [") && Streader_match_string(sr, "Af") && Streader_readf(sr, ", %f]]]", &actual))) return false; if (fabs(actual - expected) > 0.1) { Streader_set_error( sr, "Expected force %.4f, got %.4f", expected, actual); return false; } return true; }
bool read_received_events_bind(Streader* sr, int32_t index, void* userdata) { assert(sr != NULL); (void)index; assert(userdata != NULL); int32_t* expected = userdata; double actual = NAN; if (index == 0 && *expected == 0) { return Streader_readf(sr, "[0, [") && Streader_match_string(sr, "#") && Streader_match_char(sr, ',') && Streader_read_string(sr, 0, NULL) && Streader_readf(sr, "]]"); } if (!(Streader_readf(sr, "[0, [") && Streader_match_string(sr, "n+") && Streader_readf(sr, ", %f]]", &actual)) ) return false; if ((int)round(actual) != *expected) { Streader_set_error( sr, "Received argument %.0f instead of %" PRId32, actual, *expected); return false; } *expected = (int)round(actual) + 1; return true; }
static bool Streader_read_tuning(Streader* sr, double* cents) { rassert(sr != NULL); rassert(cents != NULL); if (Streader_is_error_set(sr)) return false; if (Streader_try_match_char(sr, '[')) { int64_t num = 0; int64_t den = 0; if (!Streader_readf(sr, "%i,%i]", &num, &den)) return false; if (num <= 0) { Streader_set_error(sr, "Numerator must be positive"); return false; } if (den <= 0) { Streader_set_error(sr, "Denominator must be positive"); return false; } *cents = log2((double)num / (double)den) * 1200; } else { if (!Streader_read_float(sr, cents)) return false; if (!isfinite(*cents)) { Streader_set_error(sr, "Cents value must be finite"); return false; } } 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_connection(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); rassert(userdata != NULL); ignore(index); read_conn_data* rcdata = userdata; char src_name[KQT_DEVICE_NODE_NAME_MAX] = ""; char dest_name[KQT_DEVICE_NODE_NAME_MAX] = ""; if (!Streader_readf( sr, "[%s,%s]", READF_STR(KQT_DEVICE_NODE_NAME_MAX, src_name), READF_STR(KQT_DEVICE_NODE_NAME_MAX, dest_name))) return false; int src_port = validate_connection_path( sr, src_name, rcdata->level, DEVICE_PORT_TYPE_SEND); int dest_port = validate_connection_path( sr, dest_name, rcdata->level, DEVICE_PORT_TYPE_RECV); if (Streader_is_error_set(sr)) return false; if (rcdata->level == CONNECTION_LEVEL_AU) { if (string_eq(src_name, "")) strcpy(src_name, "Iin"); } if (AAtree_get_exact(rcdata->graph->nodes, src_name) == NULL) { const Device* actual_master = rcdata->master; if ((rcdata->level == CONNECTION_LEVEL_AU) && string_eq(src_name, "Iin")) actual_master = Audio_unit_get_input_interface((Audio_unit*)rcdata->master); Device_node* new_src = new_Device_node( src_name, rcdata->au_table, actual_master); mem_error_if(new_src == NULL, rcdata->graph, NULL, sr); mem_error_if( !AAtree_ins(rcdata->graph->nodes, new_src), rcdata->graph, new_src, sr); } Device_node* src_node = AAtree_get_exact(rcdata->graph->nodes, src_name); if (AAtree_get_exact(rcdata->graph->nodes, dest_name) == NULL) { Device_node* new_dest = new_Device_node( dest_name, rcdata->au_table, rcdata->master); mem_error_if(new_dest == NULL, rcdata->graph, NULL, sr); mem_error_if( !AAtree_ins(rcdata->graph->nodes, new_dest), rcdata->graph, new_dest, sr); } Device_node* dest_node = AAtree_get_exact(rcdata->graph->nodes, dest_name); rassert(src_node != NULL); rassert(dest_node != NULL); mem_error_if( !Device_node_connect(dest_node, dest_port, src_node, src_port), rcdata->graph, NULL, sr); return true; }
static bool read_entry(Streader* sr, int32_t index, void* userdata) { rassert(sr != NULL); rassert(userdata != NULL); ignore(index); Input_map* im = userdata; int64_t in = 0; int64_t out = 0; if (!Streader_readf(sr, "[%i, %i]", &in, &out)) return false; if (in < 0 || in >= im->num_inputs) { Streader_set_error( sr, "Input ID %" PRId64 " out of range [0, %" PRId32 ")", in, im->num_inputs); return false; } if (out < 0 || out >= im->num_outputs) { Streader_set_error( sr, "Output ID %" PRId64 " out of range [0, %" PRId32 ")", out, im->num_outputs); return false; } const Entry* key = ENTRY_KEY((int32_t)in); if (AAtree_contains(im->map, key)) { Streader_set_error(sr, "Duplicate entry for input %" PRId64, in); return false; } Entry* entry = memory_alloc_item(Entry); if (entry == NULL) { Error_set( &sr->error, ERROR_MEMORY, "Could not allocate memory for input map"); return false; } entry->input = (int32_t)in; entry->output = (int32_t)out; if (!AAtree_ins(im->map, entry)) { memory_free(entry); Error_set( &sr->error, ERROR_MEMORY, "Could not allocate memory for input map"); return false; } return true; }
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, ']'); }