static SfiTokenType bse_wave_restore_private (BseObject *object, BseStorage *storage, GScanner *scanner) { BseWave *wave = BSE_WAVE (object); GTokenType expected_token; GQuark quark; /* chain parent class' handler */ if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER) return BSE_OBJECT_CLASS (parent_class)->restore_private (object, storage, scanner); /* parse storage commands */ quark = g_quark_try_string (scanner->next_value.v_identifier); if (quark == quark_xinfos) { g_scanner_get_next_token (scanner); /* eat identifier */ gchar **xinfos = NULL; GTokenType token = bse_storage_parse_xinfos (storage, &xinfos); if (token != G_TOKEN_NONE) return token; guint i = 0; for (i = 0; xinfos && xinfos[i]; i++) wave->xinfos = bse_xinfos_parse_assignment (wave->xinfos, xinfos[i]); g_strfreev (xinfos); parse_or_return (scanner, ')'); expected_token = G_TOKEN_NONE; /* got ')' */ } else if (quark == quark_load_wave) { BseFreqArray *skip_list, *load_list, *array; gchar *file_name, *wave_name; BseErrorType error; g_scanner_get_next_token (scanner); /* eat quark identifier */ parse_or_return (scanner, G_TOKEN_STRING); file_name = g_strdup (scanner->value.v_string); if (g_scanner_get_next_token (scanner) != G_TOKEN_STRING) { g_free (file_name); return G_TOKEN_STRING; } wave_name = g_strdup (scanner->value.v_string); skip_list = bse_freq_array_new (1024); load_list = bse_freq_array_new (1024); if (BSE_STORAGE_COMPAT (storage, 0, 6, 4)) while (g_scanner_get_next_token (scanner) != ')') { if (scanner->token == G_TOKEN_IDENTIFIER) { if (strcmp (scanner->value.v_identifier, "list") == 0) array = load_list; else if (strcmp (scanner->value.v_identifier, "skip") == 0) array = skip_list; else { expected_token = G_TOKEN_IDENTIFIER; /* want _valid_ identifier */ goto out_of_load_wave; } g_scanner_peek_next_token (scanner); if (scanner->next_token != G_TOKEN_INT && scanner->next_token != G_TOKEN_FLOAT) { g_scanner_get_next_token (scanner); /* eat invalid token */ expected_token = G_TOKEN_FLOAT; goto out_of_load_wave; } while (g_scanner_peek_next_token (scanner) == G_TOKEN_INT || g_scanner_peek_next_token (scanner) == G_TOKEN_FLOAT) { g_scanner_get_next_token (scanner); /* int or float */ bse_freq_array_append (array, scanner->token == G_TOKEN_FLOAT ? scanner->value.v_float : scanner->value.v_int64); } } else { expected_token = ')'; goto out_of_load_wave; } } else parse_or_return (scanner, ')'); error = bse_wave_load_wave_file (wave, file_name, wave_name, bse_freq_array_n_values (load_list) ? load_list : 0, skip_list, FALSE); if (error) bse_storage_warn (storage, "failed to load wave \"%s\" from \"%s\": %s", wave_name, file_name, bse_error_blurb (error)); expected_token = G_TOKEN_NONE; /* got ')' */ out_of_load_wave: g_free (file_name); g_free (wave_name); bse_freq_array_free (skip_list); bse_freq_array_free (load_list); } else if (BSE_STORAGE_COMPAT (storage, 0, 6, 4) && quark == quark_set_locator) { g_scanner_get_next_token (scanner); /* eat quark identifier */ parse_or_return (scanner, G_TOKEN_STRING); gchar *file_name = g_strdup (scanner->value.v_string); if (g_scanner_get_next_token (scanner) != G_TOKEN_STRING) { g_free (file_name); return G_TOKEN_STRING; } gchar *wave_name = g_strdup (scanner->value.v_string); if (g_scanner_get_next_token (scanner) != ')') { g_free (file_name); g_free (wave_name); return ')'; } // g_print ("set-locator \"%s\" \"%s\"\n", file_name, wave_name); bse_wave_set_locator (wave, file_name, wave_name); expected_token = G_TOKEN_NONE; /* got ')' */ } else if (quark == quark_wave_chunk) { ParsedWaveChunk parsed_wchunk = { NULL, NULL, 0, 0, 0 }; g_scanner_get_next_token (scanner); /* eat quark identifier */ g_scanner_peek_next_token (scanner); bse_storage_compat_dhreset (storage); /* VERSION-FIXME: needed for <= 0.5.1 */ if (scanner->next_token == G_TOKEN_FLOAT || scanner->next_token == G_TOKEN_INT) { g_scanner_get_next_token (scanner); bse_storage_compat_dhoscf (storage, /* VERSION-FIXME: needed for <= 0.5.1 */ (scanner->token == G_TOKEN_INT ? scanner->value.v_int64 : scanner->value.v_float)); g_scanner_peek_next_token (scanner); if (scanner->next_token == G_TOKEN_FLOAT || scanner->next_token == G_TOKEN_INT) { g_scanner_get_next_token (scanner); bse_storage_compat_dhmixf (storage, /* VERSION-FIXME: needed for <= 0.5.1 */ (scanner->token == G_TOKEN_INT ? scanner->value.v_int64 : scanner->value.v_float)); } } expected_token = bse_storage_parse_rest (storage, wave, (BseTryStatement) parse_wave_chunk, &parsed_wchunk); bse_storage_compat_dhreset (storage); /* VERSION-FIXME: needed for <= 0.5.1 */ if (expected_token == G_TOKEN_NONE && parsed_wchunk.data_handle) { if (0) g_printerr ("restore-wave-chunk: nch=%u of=%f mf=%f dh=%p\n", parsed_wchunk.wh_n_channels, parsed_wchunk.wh_osc_freq, parsed_wchunk.wh_mix_freq, parsed_wchunk.data_handle); if (parsed_wchunk.data_handle && parsed_wchunk.xinfos) { GslDataHandle *tmp_handle = parsed_wchunk.data_handle; parsed_wchunk.data_handle = gsl_data_handle_new_add_xinfos (parsed_wchunk.data_handle, parsed_wchunk.xinfos); gsl_data_handle_unref (tmp_handle); } GslDataCache *dcache = gsl_data_cache_from_dhandle (parsed_wchunk.data_handle, BSE_CONFIG (wave_chunk_padding) * parsed_wchunk.wh_n_channels); const gchar *ltype = bse_xinfos_get_value (parsed_wchunk.xinfos, "loop-type"); GslWaveLoopType loop_type = ltype ? gsl_wave_loop_type_from_string (ltype) : GSL_WAVE_LOOP_NONE; SfiNum loop_start = bse_xinfos_get_num (parsed_wchunk.xinfos, "loop-start"); SfiNum loop_end = bse_xinfos_get_num (parsed_wchunk.xinfos, "loop-end"); SfiNum loop_count = bse_xinfos_get_num (parsed_wchunk.xinfos, "loop-count"); if (loop_end <= loop_start) { loop_start = loop_end = 0; loop_type = GSL_WAVE_LOOP_NONE; loop_count = 0; } GslWaveChunk *wchunk = gsl_wave_chunk_new (dcache, parsed_wchunk.wh_mix_freq, parsed_wchunk.wh_osc_freq, loop_type, loop_start, loop_end, loop_count); gsl_data_cache_unref (dcache); /* we need to keep inlined data handles open to protect against storage (.bse file) overwriting */ BseErrorType error = bse_wave_add_inlined_wave_chunk (wave, wchunk); if (!error) bse_wave_add_chunk (wave, wchunk); else { bse_storage_error (storage, "failed to reopen inlined data handle (%s): %s", gsl_data_handle_name (wchunk->dcache->dhandle), bse_error_blurb (error)); gsl_wave_chunk_unref (wchunk); } } if (parsed_wchunk.data_handle) gsl_data_handle_unref (parsed_wchunk.data_handle); g_strfreev (parsed_wchunk.xinfos); } else /* chain parent class' handler */ expected_token = BSE_OBJECT_CLASS (parent_class)->restore_private (object, storage, scanner); return expected_token; }
static guint gslwave_parse_wave_dsc (GScanner *scanner, WaveDsc *dsc, const gchar *wave_name) { parse_or_return (scanner, '{'); do switch (g_scanner_get_next_token (scanner)) { guint i, token; case '}': return G_TOKEN_NONE; default: return '}'; case GSL_WAVE_TOKEN_NAME: if (dsc->wdsc.name) return '}'; parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_STRING); if (wave_name) { if (strcmp (wave_name, scanner->value.v_string) == 0) dsc->wdsc.name = g_strdup (scanner->value.v_string); else return gslwave_skip_rest_statement (scanner, 1); } else dsc->wdsc.name = g_strdup (scanner->value.v_string); break; case GSL_WAVE_TOKEN_CHUNK: if (g_scanner_peek_next_token (scanner) != '{') parse_or_return (scanner, '{'); i = dsc->wdsc.n_chunks++; dsc->wdsc.chunks = g_realloc (dsc->wdsc.chunks, sizeof (dsc->wdsc.chunks[0]) * dsc->wdsc.n_chunks); memset (dsc->wdsc.chunks + i, 0, sizeof (dsc->wdsc.chunks[0]) * 1); dsc->wdsc.chunks[i].mix_freq = dsc->dfl_mix_freq; dsc->wdsc.chunks[i].osc_freq = dsc->dfl_mix_freq; /* we check this later */ dsc->wdsc.chunks[i].loop_type = GSL_WAVE_LOOP_JUMP; dsc->wdsc.chunks[i].loop_start = GSL_MAXLONG; dsc->wdsc.chunks[i].loop_end = -1; dsc->wdsc.chunks[i].loop_count = 1000000; /* FIXME */ dsc->wdsc.chunks[i].loader_offset = 0; /* offset in bytes */ dsc->wdsc.chunks[i].loader_length = 0; /* length in n_values */ dsc->wdsc.chunks[i].loader_data1 = NULL; /* file_name */ dsc->wdsc.chunks[i].loader_data2 = NULL; /* wave_name */ token = gslwave_parse_chunk_dsc (scanner, dsc->wdsc.chunks + i); if (token != G_TOKEN_NONE) return token; if (dsc->wdsc.chunks[i].loop_end < dsc->wdsc.chunks[i].loop_start) { dsc->wdsc.chunks[i].loop_type = GSL_WAVE_LOOP_NONE; dsc->wdsc.chunks[i].loop_start = 0; dsc->wdsc.chunks[i].loop_end = 0; dsc->wdsc.chunks[i].loop_count = 0; } if (dsc->wdsc.chunks[i].osc_freq >= dsc->wdsc.chunks[i].mix_freq / 2.) g_scanner_error (scanner, "wave chunk \"%s\" mixing frequency is invalid: mix_freq=%f osc_freq=%f", dsc->wdsc.chunks[i].loader_data1 ? (gchar*) dsc->wdsc.chunks[i].loader_data1 : "", dsc->wdsc.chunks[i].mix_freq, dsc->wdsc.chunks[i].osc_freq); break; case GSL_WAVE_TOKEN_BYTE_ORDER: parse_or_return (scanner, '='); token = g_scanner_get_next_token (scanner); switch (token) { case GSL_WAVE_TOKEN_LITTLE_ENDIAN: case GSL_WAVE_TOKEN_LITTLE: dsc->byte_order = G_LITTLE_ENDIAN; break; case GSL_WAVE_TOKEN_BIG_ENDIAN: case GSL_WAVE_TOKEN_BIG: dsc->byte_order = G_BIG_ENDIAN; break; default: return GSL_WAVE_TOKEN_LITTLE_ENDIAN; } break; case GSL_WAVE_TOKEN_FORMAT: parse_or_return (scanner, '='); token = g_scanner_get_next_token (scanner); switch (token) { case GSL_WAVE_TOKEN_SIGNED_8: dsc->format = GSL_WAVE_FORMAT_SIGNED_8; break; case GSL_WAVE_TOKEN_SIGNED_12: dsc->format = GSL_WAVE_FORMAT_SIGNED_12; break; case GSL_WAVE_TOKEN_SIGNED_16: dsc->format = GSL_WAVE_FORMAT_SIGNED_16; break; case GSL_WAVE_TOKEN_UNSIGNED_8: dsc->format = GSL_WAVE_FORMAT_UNSIGNED_8; break; case GSL_WAVE_TOKEN_UNSIGNED_12: dsc->format = GSL_WAVE_FORMAT_UNSIGNED_12; break; case GSL_WAVE_TOKEN_UNSIGNED_16: dsc->format = GSL_WAVE_FORMAT_UNSIGNED_16; break; case GSL_WAVE_TOKEN_FLOAT: dsc->format = GSL_WAVE_FORMAT_FLOAT; break; default: return GSL_WAVE_TOKEN_SIGNED_16; } break; case GSL_WAVE_TOKEN_N_CHANNELS: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_INT); dsc->wdsc.n_channels = scanner->value.v_int; if (dsc->wdsc.n_channels < 1) return G_TOKEN_INT; break; case GSL_WAVE_TOKEN_MIX_FREQ: parse_or_return (scanner, '='); switch (g_scanner_get_next_token (scanner)) { case G_TOKEN_FLOAT: dsc->dfl_mix_freq = scanner->value.v_float; break; case G_TOKEN_INT: dsc->dfl_mix_freq = scanner->value.v_int; break; default: return G_TOKEN_FLOAT; } break; } while (TRUE); }
static SfiTokenType parse_wave_chunk (BseWave *wave, BseStorage *storage, GScanner *scanner, ParsedWaveChunk *pwchunk) { if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER) return SFI_TOKEN_UNMATCHED; GQuark quark = g_quark_try_string (scanner->next_value.v_string); if (quark == quark_xinfos) { g_scanner_get_next_token (scanner); /* eat identifier */ g_strfreev (pwchunk->xinfos); pwchunk->xinfos = NULL; GTokenType token = bse_storage_parse_xinfos (storage, &pwchunk->xinfos); if (token != G_TOKEN_NONE) return token; } else if (bse_storage_match_data_handle (storage, quark)) { guint expected_token; if (pwchunk->data_handle) return bse_storage_warn_skip (storage, "duplicate wave data reference"); expected_token = bse_storage_parse_data_handle_rest (storage, &pwchunk->data_handle, &pwchunk->wh_n_channels, &pwchunk->wh_mix_freq, &pwchunk->wh_osc_freq); if (expected_token != G_TOKEN_NONE) return expected_token; if (!pwchunk->data_handle) bse_storage_warn (storage, "invalid wave data reference"); /* closing brace already parsed by bse_storage_parse_data_handle_rest() */ return G_TOKEN_NONE; } else if (BSE_STORAGE_COMPAT (storage, 0, 5, 1) && quark == quark_wave_handle) { guint expected_token; g_scanner_get_next_token (scanner); /* eat identifier */ if (pwchunk->data_handle) return bse_storage_warn_skip (storage, "duplicate wave data reference"); expected_token = bse_storage_parse_data_handle (storage, &pwchunk->data_handle, &pwchunk->wh_n_channels, &pwchunk->wh_mix_freq, &pwchunk->wh_osc_freq); if (expected_token != G_TOKEN_NONE) return expected_token; if (!pwchunk->data_handle) bse_storage_warn (storage, "invalid wave data reference"); } else if (BSE_STORAGE_COMPAT (storage, 0, 5, 1) && quark == quark_n_channels) { g_scanner_get_next_token (scanner); /* eat quark identifier */ parse_or_return (scanner, G_TOKEN_INT); bse_storage_compat_dhchannels (storage, scanner->value.v_int64); } else if (BSE_STORAGE_COMPAT (storage, 0, 6, 4) && (quark == quark_loop || quark == quark_ping_pong_loop)) { g_scanner_get_next_token (scanner); /* eat quark identifier */ if (quark == quark_loop) pwchunk->xinfos = bse_xinfos_add_value (pwchunk->xinfos, "loop-type", gsl_wave_loop_type_to_string (GSL_WAVE_LOOP_JUMP)); if (quark == quark_ping_pong_loop) pwchunk->xinfos = bse_xinfos_add_value (pwchunk->xinfos, "loop-type", gsl_wave_loop_type_to_string (GSL_WAVE_LOOP_PINGPONG)); parse_or_return (scanner, G_TOKEN_INT); pwchunk->xinfos = bse_xinfos_add_num (pwchunk->xinfos, "loop-count", scanner->value.v_int64); parse_or_return (scanner, G_TOKEN_INT); pwchunk->xinfos = bse_xinfos_add_num (pwchunk->xinfos, "loop-start", scanner->value.v_int64); parse_or_return (scanner, G_TOKEN_INT); pwchunk->xinfos = bse_xinfos_add_num (pwchunk->xinfos, "loop-end", scanner->value.v_int64); } else return SFI_TOKEN_UNMATCHED; return g_scanner_get_next_token (scanner) == ')' ? G_TOKEN_NONE : ')'; }
static guint gslwave_parse_chunk_dsc (GScanner *scanner, GslWaveChunkDsc *chunk) { parse_or_return (scanner, '{'); do switch (g_scanner_get_next_token (scanner)) { case '}': return G_TOKEN_NONE; default: return '}'; case GSL_WAVE_TOKEN_FILE: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_STRING); g_free (chunk->loader_data1); /* file_name */ chunk->loader_data1 = g_strdup (scanner->value.v_string); break; case GSL_WAVE_TOKEN_INDEX: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_STRING); g_free (chunk->loader_data2); /* wave_name */ chunk->loader_data2 = g_strdup (scanner->value.v_string); break; case GSL_WAVE_TOKEN_MIX_FREQ: parse_or_return (scanner, '='); switch (g_scanner_get_next_token (scanner)) { case G_TOKEN_FLOAT: chunk->mix_freq = scanner->value.v_float; break; case G_TOKEN_INT: chunk->mix_freq = scanner->value.v_int; break; default: return G_TOKEN_FLOAT; } break; case GSL_WAVE_TOKEN_OSC_FREQ: parse_or_return (scanner, '='); switch (g_scanner_get_next_token (scanner)) { case G_TOKEN_FLOAT: chunk->osc_freq = scanner->value.v_float; break; case G_TOKEN_INT: chunk->osc_freq = scanner->value.v_int; break; default: return G_TOKEN_FLOAT; } break; case GSL_WAVE_TOKEN_MIDI_NOTE: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_INT); chunk->osc_freq = gsl_temp_freq (gsl_get_config ()->kammer_freq, scanner->value.v_int - gsl_get_config ()->midi_kammer_note); break; case GSL_WAVE_TOKEN_BOFFSET: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_INT); chunk->loader_offset = scanner->value.v_int; /* byte_offset */ break; case GSL_WAVE_TOKEN_N_VALUES: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_INT); chunk->loader_length = scanner->value.v_int; /* n_values */ break; case GSL_WAVE_TOKEN_LOOP_TYPE: parse_or_return (scanner, '='); switch (g_scanner_get_next_token (scanner)) { case GSL_WAVE_TOKEN_NONE: chunk->loop_type = GSL_WAVE_LOOP_NONE; break; case GSL_WAVE_TOKEN_JUMP: chunk->loop_type = GSL_WAVE_LOOP_JUMP; break; case GSL_WAVE_TOKEN_PINGPONG: chunk->loop_type = GSL_WAVE_LOOP_PINGPONG; break; default: return GSL_WAVE_TOKEN_JUMP; } break; case GSL_WAVE_TOKEN_LOOP_START: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_INT); chunk->loop_start = scanner->value.v_int; break; case GSL_WAVE_TOKEN_LOOP_END: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_INT); chunk->loop_end = scanner->value.v_int; break; case GSL_WAVE_TOKEN_LOOP_COUNT: parse_or_return (scanner, '='); parse_or_return (scanner, G_TOKEN_INT); chunk->loop_count = scanner->value.v_int; break; } while (TRUE); }