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 void bt_persistence_save_hashtable_entries (gpointer const key, gpointer const value, gpointer const user_data) { xmlNodePtr node; node = xmlNewChild (user_data, NULL, XML_CHAR_PTR ("property"), NULL); xmlNewProp (node, XML_CHAR_PTR ("key"), XML_CHAR_PTR (key)); xmlNewProp (node, XML_CHAR_PTR ("value"), XML_CHAR_PTR (value)); }
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 xmlNodePtr bt_sink_machine_persistence_save (const BtPersistence * const persistence, xmlNodePtr const parent_node) { //BtSinkMachine *self = BT_SINK_MACHINE(persistence); BtPersistenceInterface *const parent_iface = g_type_interface_peek_parent (BT_PERSISTENCE_GET_INTERFACE (persistence)); xmlNodePtr node = NULL; GST_DEBUG ("PERSISTENCE::sink-machine"); // save parent class stuff if ((node = parent_iface->save (persistence, parent_node))) { xmlNewProp (node, XML_CHAR_PTR ("type"), XML_CHAR_PTR ("sink")); } return node; }
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 {
/** * bt_persistence_load_hashtable: * @hashtable: (element-type utf8 utf8): a #GHashTable * @node: the list xml node * * Iterates over the xml-node and deserializes elements into the hashtable. * * Returns: %TRUE if all elements have been deserialized. */ gboolean bt_persistence_load_hashtable (GHashTable * hashtable, xmlNodePtr node) { xmlChar *key, *value; // iterate over children for (node = node->children; node; node = node->next) { if (!xmlNodeIsText (node) && !strncmp ((char *) node->name, "property\0", 9)) { key = xmlGetProp (node, XML_CHAR_PTR ("key")); value = xmlGetProp (node, XML_CHAR_PTR ("value")); //GST_DEBUG(" [%s] => [%s]",key,value); g_hash_table_insert (hashtable, key, value); // do not free, as the hastable now owns the memory //xmlFree(key);xmlFree(value); } } return TRUE; }
static xmlNodePtr bt_processor_machine_persistence_save (const BtPersistence * const persistence, xmlNodePtr const parent_node) { const BtProcessorMachine *const self = BT_PROCESSOR_MACHINE (persistence); const BtPersistenceInterface *const parent_iface = g_type_interface_peek_parent (BT_PERSISTENCE_GET_INTERFACE (persistence)); xmlNodePtr node = NULL; gchar *const plugin_name; gulong voices; GST_DEBUG ("PERSISTENCE::processor-machine"); // save parent class stuff if ((node = parent_iface->save (persistence, parent_node))) { xmlNewProp (node, XML_CHAR_PTR ("type"), XML_CHAR_PTR ("processor")); g_object_get ((gpointer) self, "plugin-name", &plugin_name, "voices", &voices, NULL); xmlNewProp (node, XML_CHAR_PTR ("plugin-name"), XML_CHAR_PTR (plugin_name)); xmlNewProp (node, XML_CHAR_PTR ("voices"), XML_CHAR_PTR (bt_str_format_ulong (voices))); g_free (plugin_name); } return node; }
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 xmlNodePtr bt_wavetable_persistence_save (const BtPersistence * const persistence, xmlNodePtr const parent_node) { const BtWavetable *const self = BT_WAVETABLE (persistence); xmlNodePtr node = NULL; GST_DEBUG ("PERSISTENCE::wavetable"); if ((node = xmlNewChild (parent_node, NULL, XML_CHAR_PTR ("wavetable"), NULL))) { bt_persistence_save_list (self->priv->waves, node); } return node; }
static xmlNodePtr bt_wavelevel_persistence_save (const BtPersistence * const persistence, xmlNodePtr const parent_node) { const BtWavelevel *const self = BT_WAVELEVEL (persistence); xmlNodePtr node = NULL; GST_DEBUG ("PERSISTENCE::wavelevel"); if ((node = xmlNewChild (parent_node, NULL, XML_CHAR_PTR ("wavelevel"), NULL))) { // only serialize customizable properties xmlNewProp (node, XML_CHAR_PTR ("root-note"), XML_CHAR_PTR (bt_str_format_uchar (self->priv->root_note))); xmlNewProp (node, XML_CHAR_PTR ("rate"), XML_CHAR_PTR (bt_str_format_ulong (self->priv->rate))); xmlNewProp (node, XML_CHAR_PTR ("loop-start"), XML_CHAR_PTR (bt_str_format_long (self->priv->loop_start))); xmlNewProp (node, XML_CHAR_PTR ("loop-end"), XML_CHAR_PTR (bt_str_format_long (self->priv->loop_end))); } return node; }
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 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; }
static xmlNodePtr bt_wave_persistence_save (const BtPersistence * const persistence, const xmlNodePtr const parent_node) { const BtWave *const self = BT_WAVE (persistence); xmlNodePtr node = NULL; xmlNodePtr child_node; GST_DEBUG ("PERSISTENCE::wave"); if ((node = xmlNewChild (parent_node, NULL, XML_CHAR_PTR ("wave"), NULL))) { BtSongIONative *song_io; // we need to have a uri if (!self->priv->uri) self->priv->uri = g_strdup (self->priv->name); xmlNewProp (node, XML_CHAR_PTR ("index"), XML_CHAR_PTR (bt_str_format_ulong (self->priv->index))); xmlNewProp (node, XML_CHAR_PTR ("name"), XML_CHAR_PTR (self->priv->name)); xmlNewProp (node, XML_CHAR_PTR ("uri"), XML_CHAR_PTR (self->priv->uri)); xmlNewProp (node, XML_CHAR_PTR ("volume"), XML_CHAR_PTR (bt_str_format_double (self->priv->volume))); xmlNewProp (node, XML_CHAR_PTR ("loop-mode"), XML_CHAR_PTR (bt_str_format_enum (BT_TYPE_WAVE_LOOP_MODE, self->priv->loop_mode))); // check if we need to save external data g_object_get (self->priv->song, "song-io", &song_io, NULL); if (song_io) { if (BT_IS_SONG_IO_NATIVE_BZT (song_io)) { gchar *uri = NULL; if (self->priv->ext_fd == -1) { // need to write in memory data to a wav bt_wave_save_to_fd (self); } uri = g_strdup_printf ("fd://%d", self->priv->ext_fd); bt_wave_save_from_fd (self, song_io, uri); g_free (uri); } g_object_unref (song_io); } // save wavelevels if ((child_node = xmlNewChild (node, NULL, XML_CHAR_PTR ("wavelevels"), NULL))) { bt_persistence_save_list (self->priv->wavelevels, child_node); } } return node; }
static xmlNodePtr bt_song_info_persistence_save (const BtPersistence * const persistence, xmlNodePtr const parent_node) { const BtSongInfo *const self = BT_SONG_INFO (persistence); xmlNodePtr node = NULL; GST_DEBUG ("PERSISTENCE::song-info"); if ((node = xmlNewChild (parent_node, NULL, XML_CHAR_PTR ("meta"), NULL))) { if (!strcmp (self->priv->name, DEFAULT_SONG_NAME)) { gchar *file_path = NULL, *file_name, *ext; bt_child_proxy_get (self->priv->song, "song-io::file-name", &file_path, NULL); if (file_path) { file_name = g_path_get_basename (file_path); if ((ext = strrchr (file_name, '.'))) { *ext = '\0'; } GST_INFO ("using '%s' instead of default title", file_name); g_object_set ((gpointer) self, "name", file_name, NULL); g_free (file_name); g_free (file_path); } } if (self->priv->info) { xmlNewChild (node, NULL, XML_CHAR_PTR ("info"), XML_CHAR_PTR (self->priv->info)); } if (self->priv->name) { xmlNewChild (node, NULL, XML_CHAR_PTR ("name"), XML_CHAR_PTR (self->priv->name)); } if (self->priv->genre) { xmlNewChild (node, NULL, XML_CHAR_PTR ("genre"), XML_CHAR_PTR (self->priv->genre)); } if (self->priv->author) { xmlNewChild (node, NULL, XML_CHAR_PTR ("author"), XML_CHAR_PTR (self->priv->author)); } if (self->priv->create_dts) { xmlNewChild (node, NULL, XML_CHAR_PTR ("create-dts"), XML_CHAR_PTR (self->priv->create_dts)); } if (self->priv->change_dts) { xmlNewChild (node, NULL, XML_CHAR_PTR ("change-dts"), XML_CHAR_PTR (self->priv->change_dts)); } xmlNewChild (node, NULL, XML_CHAR_PTR ("bpm"), XML_CHAR_PTR (bt_str_format_ulong (self->priv->beats_per_minute))); xmlNewChild (node, NULL, XML_CHAR_PTR ("tpb"), XML_CHAR_PTR (bt_str_format_ulong (self->priv->ticks_per_beat))); xmlNewChild (node, NULL, XML_CHAR_PTR ("bars"), XML_CHAR_PTR (bt_str_format_ulong (self->priv->bars))); } return node; }