static BtPersistence * bt_wavelevel_persistence_load (const GType type, const BtPersistence * const persistence, xmlNodePtr node, GError ** err, va_list var_args) { BtWavelevel *const self = BT_WAVELEVEL (persistence); xmlChar *root_note_str, *rate_str, *loop_start_str, *loop_end_str; glong loop_start, loop_end; gulong rate; GstBtNote root_note; GST_DEBUG ("PERSISTENCE::wavelevel"); g_assert (node); // only deserialize customizable properties root_note_str = xmlGetProp (node, XML_CHAR_PTR ("root-note")); rate_str = xmlGetProp (node, XML_CHAR_PTR ("rate")); loop_start_str = xmlGetProp (node, XML_CHAR_PTR ("loop-start")); loop_end_str = xmlGetProp (node, XML_CHAR_PTR ("loop-end")); root_note = root_note_str ? atol ((char *) root_note_str) : GSTBT_NOTE_NONE; rate = rate_str ? atol ((char *) rate_str) : 0; loop_start = loop_start_str ? atol ((char *) loop_start_str) : 0; loop_end = loop_end_str ? atol ((char *) loop_end_str) : self->priv->length; g_object_set (self, "root-note", root_note, "rate", rate, "loop-start", loop_start, "loop-end", loop_end, NULL); xmlFree (root_note_str); xmlFree (rate_str); xmlFree (loop_start_str); xmlFree (loop_end_str); return BT_PERSISTENCE (persistence); }
static BtPersistence * bt_wave_persistence_load (const GType type, const BtPersistence * const persistence, xmlNodePtr node, GError ** err, va_list var_args) { BtWave *self; BtPersistence *result; BtSongIONative *song_io; gchar *uri = NULL; GST_DEBUG ("PERSISTENCE::wave"); g_assert (node); xmlChar *const index_str = xmlGetProp (node, XML_CHAR_PTR ("index")); const gulong index = index_str ? atol ((char *) index_str) : 0; xmlChar *const name = xmlGetProp (node, XML_CHAR_PTR ("name")); xmlChar *const uri_str = xmlGetProp (node, XML_CHAR_PTR ("uri")); xmlChar *const volume_str = xmlGetProp (node, XML_CHAR_PTR ("volume")); const gdouble volume = volume_str ? g_ascii_strtod ((char *) volume_str, NULL) : 0.0; xmlChar *const loop_mode_str = xmlGetProp (node, XML_CHAR_PTR ("loop-mode")); gint loop_mode = bt_str_parse_enum (BT_TYPE_WAVE_LOOP_MODE, (char *) loop_mode_str); if (loop_mode == -1) loop_mode = BT_WAVE_LOOP_MODE_OFF; if (!persistence) { BtSong *song = NULL; gchar *param_name; // we need to get parameters from var_args (need to handle all baseclass params param_name = va_arg (var_args, gchar *); while (param_name) { if (!strcmp (param_name, "song")) { song = va_arg (var_args, gpointer); } else { GST_WARNING ("unhandled argument: %s", param_name); break; } param_name = va_arg (var_args, gchar *); } /* TODO(ensonic): ugly hack, don't pass uri_str yet, this would trigger loading * which we do below (see also: bt_wave_constructed) */ self = bt_wave_new (song, (gchar *) name, NULL, index, volume, loop_mode, 0); result = BT_PERSISTENCE (self); g_object_set (self, "uri", uri_str, NULL); } else {
static gboolean bt_song_io_native_xml_save (gconstpointer const _self, const BtSong * const song, GError ** err) { const BtSongIONativeXML *const self = BT_SONG_IO_NATIVE_XML (_self); gboolean result = FALSE; gchar *const file_name; g_object_get ((gpointer) self, "file-name", &file_name, NULL); GST_INFO ("native io xml will now save song to \"%s\"", file_name ? file_name : "data"); xmlDocPtr const song_doc = xmlNewDoc (XML_CHAR_PTR ("1.0")); if (song_doc) { xmlNodePtr const root_node = bt_persistence_save (BT_PERSISTENCE (song), NULL); if (root_node) { xmlDocSetRootElement (song_doc, root_node); if (file_name) { if (xmlSaveFile (file_name, song_doc) != -1) { result = TRUE; GST_INFO ("xml saved okay"); } else { GST_WARNING ("failed to write song file \"%s\"", file_name); g_set_error_literal (err, G_IO_ERROR, g_io_error_from_errno (errno), g_strerror (errno)); } } else { xmlChar *mem; guint len; gpointer data; xmlDocDumpMemory (song_doc, &mem, (int *) &len); data = g_memdup (mem, len); xmlFree (mem); g_object_set ((gpointer) self, "data", data, "data-len", len, NULL); } } else { g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to serialize XML doc."); } } else { g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to create XML doc."); } g_free (file_name); return result; }
static BtPersistence * bt_processor_machine_persistence_load (const GType type, const BtPersistence * const persistence, xmlNodePtr node, GError ** err, va_list var_args) { BtProcessorMachine *self; BtPersistence *result; BtPersistenceInterface *parent_iface; gulong voices; GST_DEBUG ("PERSISTENCE::processor_machine"); g_assert (node); xmlChar *const id = xmlGetProp (node, XML_CHAR_PTR ("id")); xmlChar *const plugin_name = xmlGetProp (node, XML_CHAR_PTR ("plugin-name")); xmlChar *const voices_str = xmlGetProp (node, XML_CHAR_PTR ("voices")); voices = voices_str ? atol ((char *) voices_str) : 0; if (!persistence) { BtSong *song = NULL; gchar *param_name; va_list va; G_VA_COPY (va, var_args); // we need to get parameters from var_args (need to handle all baseclass params param_name = va_arg (va, gchar *); while (param_name) { if (!strcmp (param_name, "song")) { song = va_arg (va, gpointer); } else { GST_WARNING ("unhandled argument: %s", param_name); break; } param_name = va_arg (va, gchar *); } // TODO(ensonic): we also need the parameters the parent-class would parse // as a a quick hack copied the code from the parent class into the subclasses // see : http://www.buzztrax.org/index.php/Gobject_serialisation#Dealing_with_inheritance self = bt_processor_machine_new (song, (gchar *) id, (gchar *) plugin_name, voices, err); result = BT_PERSISTENCE (self); va_end (va); } else {
static BtPersistence * bt_song_info_persistence_load (const GType type, const BtPersistence * const persistence, xmlNodePtr node, GError ** err, va_list var_args) { const BtSongInfo *const self = BT_SONG_INFO (persistence); GST_DEBUG ("PERSISTENCE::song-info"); g_assert (node); for (node = node->children; node; node = node->next) { if (!xmlNodeIsText (node)) { xmlNodePtr const child_node = node->children; if (child_node && xmlNodeIsText (child_node) && !xmlIsBlankNode (child_node)) { xmlChar *const elem = xmlNodeGetContent (child_node); if (elem) { const gchar *const property_name = (gchar *) node->name; GST_DEBUG (" \"%s\"=\"%s\"", property_name, elem); // depending on the name of the property, treat it's type if (!strncmp (property_name, "info", 4) || !strncmp (property_name, "name", 4) || !strncmp (property_name, "genre", 5) || !strncmp (property_name, "author", 6) || !strncmp (property_name, "create-dts", 10) || !strncmp (property_name, "change-dts", 10) ) { g_object_set ((gpointer) self, property_name, elem, NULL); } else if (!strncmp (property_name, "bpm", 3) || !strncmp (property_name, "tpb", 3) || !strncmp (property_name, "bars", 4)) { g_object_set ((gpointer) self, property_name, atol ((char *) elem), NULL); } xmlFree (elem); } } } } return BT_PERSISTENCE (persistence); }
static BtPersistence * bt_sink_machine_persistence_load (const GType type, const BtPersistence * const persistence, xmlNodePtr node, GError ** err, va_list var_args) { BtSinkMachine *self; BtPersistence *result; BtPersistenceInterface *parent_iface; GST_DEBUG ("PERSISTENCE::sink_machine"); g_assert (node); xmlChar *const id = xmlGetProp (node, XML_CHAR_PTR ("id")); if (!persistence) { BtSong *song = NULL; gchar *param_name; va_list va; G_VA_COPY (va, var_args); // we need to get parameters from var_args // TODO(ensonic): this is duplicated code among the subclasses param_name = va_arg (va, gchar *); while (param_name) { if (!strcmp (param_name, "song")) { song = va_arg (va, gpointer); } else { GST_WARNING ("unhandled argument: %s", param_name); break; } param_name = va_arg (va, gchar *); } self = bt_sink_machine_new (song, (gchar *) id, err); result = BT_PERSISTENCE (self); va_end (va); } else {
static BtPersistence * bt_wavetable_persistence_load (const GType type, const BtPersistence * const persistence, xmlNodePtr node, GError ** err, va_list var_args) { const BtWavetable *const self = BT_WAVETABLE (persistence); xmlNodePtr child_node; GST_DEBUG ("PERSISTENCE::wavetable"); g_assert (node); for (child_node = node->children; child_node; child_node = child_node->next) { if ((!xmlNodeIsText (child_node)) && (!strncmp ((char *) child_node->name, "wave\0", 5))) { GError *err = NULL; BtWave *const wave = BT_WAVE (bt_persistence_load (BT_TYPE_WAVE, NULL, child_node, &err, "song", self->priv->song, NULL)); if (err != NULL) { // collect failed waves gchar *const name, *const uri; g_object_get (wave, "name", &name, "uri", &uri, NULL); gchar *const str = g_strdup_printf ("%s: %s", name, uri); bt_wavetable_remember_missing_wave (self, str); g_free (name); g_free (uri); GST_WARNING ("Can't create wavetable: %s", err->message); g_error_free (err); } g_object_unref (wave); } } return BT_PERSISTENCE (persistence); }
static void test_bt_wire_persistence (BT_TEST_ARGS) { BT_TEST_START; GST_INFO ("-- arrange --"); BtMachine *src = BT_MACHINE (bt_source_machine_new (song, "audiotestsrc", "audiotestsrc", 0L, NULL)); BtMachine *proc = BT_MACHINE (bt_processor_machine_new (song, "volume", "volume", 0L, NULL)); BtWire *wire = bt_wire_new (song, src, proc, NULL); GST_INFO ("-- act --"); xmlNodePtr parent = xmlNewNode (NULL, XML_CHAR_PTR ("buzztrax")); xmlNodePtr node = bt_persistence_save (BT_PERSISTENCE (wire), parent); GST_INFO ("-- assert --"); fail_unless (node != NULL, NULL); ck_assert_str_eq ((gchar *) node->name, "wire"); fail_unless (node->children != NULL, NULL); GST_INFO ("-- cleanup --"); BT_TEST_END; }