[beast/wip/soundfont: 13/832] BSE: added sound font support for bse projects wrapping fluid synths structures.
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast/wip/soundfont: 13/832] BSE: added sound font support for bse projects wrapping fluid synths structures.
- Date: Sun, 6 Nov 2016 11:50:02 +0000 (UTC)
commit a2138869b4ba39d6c67ed987c9823c7fbdc92ae4
Author: Stefan Westerfeld <stefan space twc de>
Date: Mon Nov 8 23:07:48 2010 +0100
BSE: added sound font support for bse projects wrapping fluid synths structures.
bse/bsesoundfont.c | 394 +++++++++++++++++++++++++++++++++++++++++++++
bse/bsesoundfont.h | 59 +++++++
bse/bsesoundfontpreset.c | 195 ++++++++++++++++++++++
bse/bsesoundfontpreset.h | 54 ++++++
bse/bsesoundfontrepo.c | 393 ++++++++++++++++++++++++++++++++++++++++++++
bse/bsesoundfontrepo.h | 94 +++++++++++
bse/bsesoundfontrepo.proc | 155 ++++++++++++++++++
7 files changed, 1344 insertions(+), 0 deletions(-)
---
diff --git a/bse/bsesoundfont.c b/bse/bsesoundfont.c
new file mode 100644
index 0000000..096d749
--- /dev/null
+++ b/bse/bsesoundfont.c
@@ -0,0 +1,394 @@
+/* BSE - Bedevilled Sound Engine
+ * Copyright (C) 1997-1999, 2000-2005 Tim Janik
+ * Copyright (C) 2009 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#include "bsesoundfont.h"
+#include "bsesoundfontrepo.h"
+#include "bsesoundfontpreset.h"
+#include "bsemain.h"
+#include "bsestorage.h"
+#include "bseprocedure.h"
+#include "gsldatahandle.h"
+#include "bseserver.h"
+#include "bseloader.h"
+
+#include <string.h>
+
+#define parse_or_return bse_storage_scanner_parse_or_return
+
+enum {
+ PARAM_0,
+ PARAM_FILE_NAME,
+};
+
+/* --- prototypes --- */
+
+
+/* --- variables --- */
+static GTypeClass *parent_class = NULL;
+static GQuark quark_load_sound_font = 0;
+
+
+/* --- functions --- */
+static void
+bse_sound_font_init (BseSoundFont *sound_font)
+{
+ sound_font->blob = NULL;
+ sound_font->sfont_id = -1;
+ sound_font->sfrepo = NULL;
+}
+
+static void
+bse_sound_font_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (param_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+bse_sound_font_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (object);
+ switch (param_id)
+ {
+ case PARAM_FILE_NAME:
+ if (sound_font->blob)
+ sfi_value_set_string (value, bse_storage_blob_file_name (sound_font->blob));
+ else
+ sfi_value_set_string (value, NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+bse_sound_font_dispose (GObject *object)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (object);
+ if (sound_font->sfont_id != -1)
+ bse_sound_font_unload (sound_font);
+ if (sound_font->sfrepo)
+ {
+ g_object_unref (sound_font->sfrepo);
+ sound_font->sfrepo = NULL;
+ }
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+bse_sound_font_finalize (GObject *object)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (object);
+
+ /* free blob */
+ if (sound_font->blob)
+ {
+ bse_storage_blob_unref (sound_font->blob);
+ sound_font->blob = NULL;
+ }
+
+ if (sound_font->sfrepo != NULL || sound_font->blob != NULL || sound_font->sfont_id != -1)
+ g_warning (G_STRLOC ": some resources could not be freed.");
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+BseErrorType
+bse_sound_font_load_blob (BseSoundFont *self,
+ BseStorageBlob *blob,
+ gboolean init_presets)
+{
+ if (self->sfrepo == NULL)
+ {
+ self->sfrepo = BSE_SOUND_FONT_REPO (BSE_ITEM (self)->parent);
+ g_object_ref (self->sfrepo);
+ }
+
+ g_return_val_if_fail (blob != NULL, BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (self->sfrepo != NULL, BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (self->sfont_id == -1, BSE_ERROR_INTERNAL);
+
+ bse_storage_blob_ref (blob);
+ if (self->blob)
+ {
+ bse_storage_blob_unref (self->blob);
+ self->blob = NULL;
+ }
+
+ fluid_synth_t *fluid_synth = bse_sound_font_repo_lock_fluid_synth (self->sfrepo);
+ int sfont_id = fluid_synth_sfload (fluid_synth, bse_storage_blob_file_name (blob), 0);
+ BseErrorType error;
+ if (sfont_id != -1)
+ {
+ if (init_presets)
+ {
+ fluid_sfont_t *fluid_sfont = fluid_synth_get_sfont_by_id (fluid_synth, sfont_id);
+ fluid_preset_t fluid_preset;
+
+ fluid_sfont->iteration_start (fluid_sfont);
+ while (fluid_sfont->iteration_next (fluid_sfont, &fluid_preset))
+ {
+ BseSoundFontPreset *sound_font_preset = g_object_new (BSE_TYPE_SOUND_FONT_PRESET,
+ "uname", fluid_preset.get_name
(&fluid_preset),
+ NULL);
+ bse_container_add_item (BSE_CONTAINER (self), BSE_ITEM (sound_font_preset));
+ bse_sound_font_preset_init_preset (sound_font_preset, &fluid_preset);
+ }
+ }
+ self->sfont_id = sfont_id;
+ self->blob = blob;
+ error = BSE_ERROR_NONE;
+ }
+ else
+ {
+ bse_storage_blob_unref (blob);
+ error = BSE_ERROR_WAVE_NOT_FOUND;
+ }
+ bse_sound_font_repo_unlock_fluid_synth (self->sfrepo);
+ return error;
+}
+
+void
+bse_sound_font_unload (BseSoundFont *sound_font)
+{
+ g_return_if_fail (sound_font->sfrepo != NULL);
+
+ if (sound_font->sfont_id != -1)
+ {
+ fluid_synth_t *fluid_synth = bse_sound_font_repo_lock_fluid_synth (sound_font->sfrepo);
+ fluid_synth_sfunload (fluid_synth, sound_font->sfont_id, 1 /* reset presets */);
+ bse_sound_font_repo_unlock_fluid_synth (sound_font->sfrepo);
+ }
+ sound_font->sfont_id = -1;
+}
+
+BseErrorType
+bse_sound_font_reload (BseSoundFont *sound_font)
+{
+ g_return_val_if_fail (sound_font->sfont_id == -1, BSE_ERROR_INTERNAL);
+
+ return bse_sound_font_load_blob (sound_font, sound_font->blob, FALSE);
+}
+
+static void
+bse_sound_font_store_private (BseObject *object,
+ BseStorage *storage)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (object);
+ /* chain parent class' handler */
+ BSE_OBJECT_CLASS (parent_class)->store_private (object, storage);
+
+ if (!BSE_STORAGE_SELF_CONTAINED (storage) && !bse_storage_blob_is_temp_file (sound_font->blob))
+ {
+ bse_storage_break (storage);
+ bse_storage_printf (storage, "(load-sound-font \"%s\")", bse_storage_blob_file_name
(sound_font->blob));
+ }
+ else
+ {
+ bse_storage_break (storage);
+ bse_storage_printf (storage, "(load-sound-font ");
+ bse_storage_put_blob (storage, sound_font->blob);
+ bse_storage_printf (storage, ")");
+ }
+}
+
+static SfiTokenType
+bse_sound_font_restore_private (BseObject *object,
+ BseStorage *storage,
+ GScanner *scanner)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (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_load_sound_font)
+ {
+ BseStorageBlob *blob;
+ BseErrorType error;
+
+ g_scanner_get_next_token (scanner); /* eat quark identifier */
+ if (g_scanner_peek_next_token (scanner) == G_TOKEN_STRING)
+ {
+ parse_or_return (scanner, G_TOKEN_STRING);
+ blob = bse_storage_blob_new_from_file (scanner->value.v_string, FALSE);
+ }
+ else
+ {
+ GTokenType token = bse_storage_parse_blob (storage, &blob);
+ if (token != G_TOKEN_NONE)
+ {
+ if (blob)
+ bse_storage_blob_unref (blob);
+ return token;
+ }
+ }
+ if (g_scanner_peek_next_token (scanner) != ')')
+ {
+ bse_storage_blob_unref (blob);
+ return ')';
+ }
+ parse_or_return (scanner, ')');
+ error = bse_sound_font_load_blob (sound_font, blob, FALSE);
+ if (error)
+ bse_storage_warn (storage, "failed to load sound font \"%s\": %s",
+ bse_storage_blob_file_name (blob), bse_error_blurb (error));
+ bse_storage_blob_unref (blob);
+ expected_token = G_TOKEN_NONE; /* got ')' */
+ }
+ else /* chain parent class' handler */
+ expected_token = BSE_OBJECT_CLASS (parent_class)->restore_private (object, storage, scanner);
+
+ return expected_token;
+}
+
+
+static void
+bse_sound_font_add_item (BseContainer *container,
+ BseItem *item)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (container);
+
+ if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT_PRESET))
+ sound_font->presets = g_list_append (sound_font->presets, item);
+ else
+ g_warning ("BseSoundFont: cannot hold non-sound-font-preset item type `%s'",
+ BSE_OBJECT_TYPE_NAME (item));
+
+ /* chain parent class' add_item handler */
+ BSE_CONTAINER_CLASS (parent_class)->add_item (container, item);
+}
+
+static void
+bse_sound_font_forall_items (BseContainer *container,
+ BseForallItemsFunc func,
+ gpointer data)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (container);
+ GList *list;
+
+ list = sound_font->presets;
+ while (list)
+ {
+ BseItem *item;
+
+ item = list->data;
+ list = list->next;
+ if (!func (item, data))
+ return;
+ }
+}
+
+static void
+bse_sound_font_remove_item (BseContainer *container,
+ BseItem *item)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (container);
+
+ if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT_PRESET))
+ sound_font->presets = g_list_remove (sound_font->presets, item);
+ else
+ g_warning ("BseSoundFontRepo: cannot hold non-sound-font-preset item type `%s'",
+ BSE_OBJECT_TYPE_NAME (item));
+
+ /* chain parent class' remove_item handler */
+ BSE_CONTAINER_CLASS (parent_class)->remove_item (container, item);
+}
+
+static void
+bse_sound_font_release_children (BseContainer *container)
+{
+ BseSoundFont *self = BSE_SOUND_FONT (container);
+
+ while (self->presets)
+ bse_container_remove_item (container, self->presets->data);
+
+ /* chain parent class' handler */
+ BSE_CONTAINER_CLASS (parent_class)->release_children (container);
+}
+
+
+static void
+bse_sound_font_class_init (BseSoundFontClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ BseObjectClass *object_class = BSE_OBJECT_CLASS (class);
+ BseContainerClass *container_class = BSE_CONTAINER_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ gobject_class->set_property = bse_sound_font_set_property;
+ gobject_class->get_property = bse_sound_font_get_property;
+ gobject_class->dispose = bse_sound_font_dispose;
+ gobject_class->finalize = bse_sound_font_finalize;
+
+ container_class->add_item = bse_sound_font_add_item;
+ container_class->remove_item = bse_sound_font_remove_item;
+ container_class->forall_items = bse_sound_font_forall_items;
+ container_class->release_children = bse_sound_font_release_children;
+
+ object_class->store_private = bse_sound_font_store_private;
+ object_class->restore_private = bse_sound_font_restore_private;
+
+ quark_load_sound_font = g_quark_from_static_string ("load-sound-font");
+
+ bse_object_class_add_param (object_class, "Locator",
+ PARAM_FILE_NAME,
+ sfi_pspec_string ("file_name", "File Name", NULL,
+ NULL, "G:r"));
+}
+
+BSE_BUILTIN_TYPE (BseSoundFont)
+{
+ static const GTypeInfo sound_font_info = {
+ sizeof (BseSoundFontClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) bse_sound_font_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL /* class_data */,
+
+ sizeof (BseSoundFont),
+ 0 /* n_preallocs */,
+ (GInstanceInitFunc) bse_sound_font_init,
+ };
+
+ return bse_type_register_static (BSE_TYPE_CONTAINER,
+ "BseSoundFont",
+ "BSE sound_font type",
+ __FILE__, __LINE__,
+ &sound_font_info);
+}
diff --git a/bse/bsesoundfont.h b/bse/bsesoundfont.h
new file mode 100644
index 0000000..6705f8e
--- /dev/null
+++ b/bse/bsesoundfont.h
@@ -0,0 +1,59 @@
+/* BSE - Bedevilled Sound Engine
+ * Copyright (C) 1997-1999, 2000-2005 Tim Janik
+ * Copyright (C) 2009 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#ifndef __BSE_SOUND_FONT_H__
+#define __BSE_SOUND_FONT_H__
+
+#include <bse/bsecontainer.h>
+#include <bse/bsestorage.h>
+
+G_BEGIN_DECLS
+
+/* --- BSE type macros --- */
+#define BSE_TYPE_SOUND_FONT (BSE_TYPE_ID (BseSoundFont))
+#define BSE_SOUND_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), BSE_TYPE_SOUND_FONT,
BseSoundFont))
+#define BSE_SOUND_FONT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), BSE_TYPE_SOUND_FONT,
BseSoundFontClass))
+#define BSE_IS_SOUND_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), BSE_TYPE_SOUND_FONT))
+#define BSE_IS_SOUND_FONT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), BSE_TYPE_SOUND_FONT))
+#define BSE_SOUND_FONT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), BSE_TYPE_SOUND_FONT,
BseSoundFontClass))
+
+
+/* --- BseSoundFont --- */
+struct _BseSoundFont
+{
+ BseContainer parent_object;
+ BseStorageBlob *blob;
+ int sfont_id;
+ BseSoundFontRepo *sfrepo;
+ GList *presets;
+};
+struct _BseSoundFontClass
+{
+ BseContainerClass parent_class;
+};
+
+
+/* --- prototypes -- */
+BseErrorType bse_sound_font_load_blob (BseSoundFont *sound_font,
+ BseStorageBlob *blob,
+ gboolean init_presets);
+void bse_sound_font_unload (BseSoundFont *sound_font);
+BseErrorType bse_sound_font_reload (BseSoundFont *sound_font);
+
+G_END_DECLS
+
+#endif /* __BSE_SOUND_FONT_H__ */
diff --git a/bse/bsesoundfontpreset.c b/bse/bsesoundfontpreset.c
new file mode 100644
index 0000000..9de08b3
--- /dev/null
+++ b/bse/bsesoundfontpreset.c
@@ -0,0 +1,195 @@
+/* BSE - Bedevilled Sound Engine
+ * Copyright (C) 1997-1999, 2000-2005 Tim Janik
+ * Copyright (C) 2009 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#include "bsesoundfontpreset.h"
+#include "bsemain.h"
+#include "bsestorage.h"
+#include "bseprocedure.h"
+#include "gsldatahandle.h"
+#include "bseserver.h"
+#include "bseloader.h"
+
+#include <string.h>
+#include <fluidsynth.h>
+
+#define parse_or_return bse_storage_scanner_parse_or_return
+
+/* --- variables --- */
+static GTypeClass *parent_class = NULL;
+static GQuark quark_program = 0;
+static GQuark quark_bank = 0;
+
+
+/* --- functions --- */
+static void
+bse_sound_font_preset_init (BseSoundFontPreset *sound_font_preset)
+{
+ // init members here
+}
+
+void
+bse_sound_font_preset_init_preset (BseSoundFontPreset *self,
+ fluid_preset_t *fluid_preset)
+{
+ self->bank = fluid_preset->get_banknum (fluid_preset);
+ self->program = fluid_preset->get_num (fluid_preset);
+}
+
+static void
+bse_sound_font_preset_store_private (BseObject *object,
+ BseStorage *storage)
+{
+ BseSoundFontPreset *self = BSE_SOUND_FONT_PRESET (object);
+ /* chain parent class' handler */
+ BSE_OBJECT_CLASS (parent_class)->store_private (object, storage);
+
+ bse_storage_break (storage);
+ bse_storage_printf (storage, "(bank %d)", self->bank);
+ bse_storage_break (storage);
+ bse_storage_printf (storage, "(program %d)", self->program);
+}
+
+static SfiTokenType
+bse_sound_font_preset_restore_private (BseObject *object,
+ BseStorage *storage,
+ GScanner *scanner)
+{
+ BseSoundFontPreset *sound_font_preset = BSE_SOUND_FONT_PRESET (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_program)
+ {
+ g_scanner_get_next_token (scanner); /* eat quark identifier */
+ parse_or_return (scanner, G_TOKEN_INT);
+ sound_font_preset->program = scanner->value.v_int;
+ parse_or_return (scanner, ')');
+ expected_token = G_TOKEN_NONE; /* got ')' */
+ }
+ else if (quark == quark_bank)
+ {
+ g_scanner_get_next_token (scanner); /* eat quark identifier */
+ parse_or_return (scanner, G_TOKEN_INT);
+ sound_font_preset->bank = scanner->value.v_int;
+ parse_or_return (scanner, ')');
+ expected_token = G_TOKEN_NONE; /* got ')' */
+ }
+ else /* chain parent class' handler */
+ expected_token = BSE_OBJECT_CLASS (parent_class)->restore_private (object, storage, scanner);
+
+ return expected_token;
+}
+
+
+
+static void
+bse_sound_font_preset_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (param_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+bse_sound_font_preset_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ // BseSoundFontPreset *sound_font_preset = BSE_SOUND_FONT_PRESET (object);
+ switch (param_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+bse_sound_font_preset_dispose (GObject *object)
+{
+ // BseSoundFontPreset *sound_font_preset = BSE_SOUND_FONT_PRESET (object);
+ // bse_sound_font_preset_clear (sound_font_preset);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+bse_sound_font_preset_finalize (GObject *object)
+{
+ // BseSoundFontPreset *sound_font_preset = BSE_SOUND_FONT_PRESET (object);
+ // bse_sound_font_preset_clear (sound_font_preset);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+bse_sound_font_preset_class_init (BseSoundFontPresetClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ BseObjectClass *object_class = BSE_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ gobject_class->set_property = bse_sound_font_preset_set_property;
+ gobject_class->get_property = bse_sound_font_preset_get_property;
+ gobject_class->dispose = bse_sound_font_preset_dispose;
+ gobject_class->finalize = bse_sound_font_preset_finalize;
+
+ object_class->store_private = bse_sound_font_preset_store_private;
+ object_class->restore_private = bse_sound_font_preset_restore_private;
+
+ quark_program = g_quark_from_static_string ("program");
+ quark_bank = g_quark_from_static_string ("bank");
+}
+
+BSE_BUILTIN_TYPE (BseSoundFontPreset)
+{
+ static const GTypeInfo sound_font_preset_info = {
+ sizeof (BseSoundFontPresetClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) bse_sound_font_preset_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL /* class_data */,
+
+ sizeof (BseSoundFontPreset),
+ 0 /* n_preallocs */,
+ (GInstanceInitFunc) bse_sound_font_preset_init,
+ };
+
+ return bse_type_register_static (BSE_TYPE_ITEM,
+ "BseSoundFontPreset",
+ "BSE sound_font_preset type",
+ __FILE__, __LINE__,
+ &sound_font_preset_info);
+}
diff --git a/bse/bsesoundfontpreset.h b/bse/bsesoundfontpreset.h
new file mode 100644
index 0000000..a90b931
--- /dev/null
+++ b/bse/bsesoundfontpreset.h
@@ -0,0 +1,54 @@
+/* BSE - Bedevilled Sound Engine
+ * Copyright (C) 1997-1999, 2000-2005 Tim Janik
+ * Copyright (C) 2009 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#ifndef __BSE_SOUND_FONT_PRESET_H__
+#define __BSE_SOUND_FONT_PRESET_H__
+
+#include <bse/bseitem.h>
+#include <fluidsynth.h>
+
+G_BEGIN_DECLS
+
+/* --- BSE type macros --- */
+#define BSE_TYPE_SOUND_FONT_PRESET (BSE_TYPE_ID (BseSoundFontPreset))
+#define BSE_SOUND_FONT_PRESET(object) (G_TYPE_CHECK_INSTANCE_CAST ((object),
BSE_TYPE_SOUND_FONT_PRESET, BseSoundFontPreset))
+#define BSE_SOUND_FONT_PRESET_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),
BSE_TYPE_SOUND_FONT_PRESET, BseSoundFontPresetClass))
+#define BSE_IS_SOUND_FONT_PRESET(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object),
BSE_TYPE_SOUND_FONT_PRESET))
+#define BSE_IS_SOUND_FONT_PRESET_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),
BSE_TYPE_SOUND_FONT_PRESET))
+#define BSE_SOUND_FONT_PRESET_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object),
BSE_TYPE_SOUND_FONT_PRESET, BseSoundFontPresetClass))
+
+
+/* --- BseSoundFontPreset --- */
+struct _BseSoundFontPreset
+{
+ BseItem parent_object;
+ int program;
+ int bank;
+};
+struct _BseSoundFontPresetClass
+{
+ BseItemClass parent_class;
+};
+
+
+/* --- prototypes -- */
+void bse_sound_font_preset_init_preset (BseSoundFontPreset *self,
+ fluid_preset_t *fluid_preset);
+
+G_END_DECLS
+
+#endif /* __BSE_SOUND_FONT_PRESET_H__ */
diff --git a/bse/bsesoundfontrepo.c b/bse/bsesoundfontrepo.c
new file mode 100644
index 0000000..00c321b
--- /dev/null
+++ b/bse/bsesoundfontrepo.c
@@ -0,0 +1,393 @@
+/* BSE - Bedevilled Sound Engine
+ * Copyright (C) 1996-1999, 2000-2003 Tim Janik
+ * Copyright (C) 2009 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#include "bsesoundfontrepo.h"
+#include "bsesoundfont.h"
+#include "bsesoundfontpreset.h"
+#include "bsedefs.h"
+#include "bseblockutils.hh"
+
+
+/* --- parameters --- */
+enum
+{
+ PARAM_0,
+};
+
+
+/* --- prototypes --- */
+static void bse_sound_font_repo_class_init (BseSoundFontRepoClass *class);
+static void bse_sound_font_repo_init (BseSoundFontRepo *wrepo);
+static void bse_sound_font_repo_dispose (GObject *object);
+static void bse_sound_font_repo_release_children (BseContainer *container);
+static void bse_sound_font_repo_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void bse_sound_font_repo_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void bse_sound_font_repo_add_item (BseContainer *container,
+ BseItem *item);
+static void bse_sound_font_repo_forall_items (BseContainer *container,
+ BseForallItemsFunc func,
+ gpointer data);
+static void bse_sound_font_repo_remove_item (BseContainer *container,
+ BseItem *item);
+static void bse_sound_font_repo_prepare (BseSource *source);
+
+
+/* --- variables --- */
+static GTypeClass *parent_class = NULL;
+
+
+/* --- functions --- */
+BSE_BUILTIN_TYPE (BseSoundFontRepo)
+{
+ GType sound_font_repo_type;
+
+ static const GTypeInfo sfrepo_info = {
+ sizeof (BseSoundFontRepoClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) bse_sound_font_repo_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL /* class_data */,
+
+ sizeof (BseSoundFontRepo),
+ 0,
+ (GInstanceInitFunc) bse_sound_font_repo_init,
+ };
+
+ sound_font_repo_type = bse_type_register_static (BSE_TYPE_SUPER,
+ "BseSoundFontRepo",
+ "BSE Sound Font Repository",
+ __FILE__, __LINE__,
+ &sfrepo_info);
+ return sound_font_repo_type;
+}
+
+static void
+bse_sound_font_repo_class_init (BseSoundFontRepoClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ BseContainerClass *container_class = BSE_CONTAINER_CLASS (class);
+ BseSourceClass *source_class = BSE_SOURCE_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ gobject_class->set_property = bse_sound_font_repo_set_property;
+ gobject_class->get_property = bse_sound_font_repo_get_property;
+ gobject_class->dispose = bse_sound_font_repo_dispose;
+
+ container_class->add_item = bse_sound_font_repo_add_item;
+ container_class->remove_item = bse_sound_font_repo_remove_item;
+ container_class->forall_items = bse_sound_font_repo_forall_items;
+ container_class->release_children = bse_sound_font_repo_release_children;
+
+ source_class->prepare = bse_sound_font_repo_prepare;
+}
+
+static void
+bse_sound_font_repo_init (BseSoundFontRepo *sfrepo)
+{
+ sfi_mutex_init (&sfrepo->fluid_synth_mutex);
+
+ sfrepo->n_oscs = 0;
+ sfrepo->oscs = NULL;
+ sfrepo->channel_map = NULL;
+
+ sfrepo->fluid_settings = new_fluid_settings();
+ sfrepo->fluid_synth = new_fluid_synth (sfrepo->fluid_settings);
+ sfrepo->fluid_events = NULL;
+ sfrepo->sound_fonts = NULL;
+ sfrepo->fluid_mix_freq = 0;
+
+ sfrepo->n_fluid_channels = 0;
+ sfrepo->channel_values_left = NULL;
+ sfrepo->channel_values_right = NULL;
+ sfrepo->n_silence_samples = NULL;
+
+ sfrepo->n_channel_oscs_active = 0;
+ sfrepo->channel_values_tick_stamp = 0;
+}
+
+static gboolean
+reload_sound_font (BseItem *item,
+ gpointer data)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (item);
+ bse_sound_font_reload (sound_font);
+ return TRUE;
+}
+
+static gboolean
+unload_sound_font (BseItem *item,
+ gpointer data)
+{
+ BseSoundFont *sound_font = BSE_SOUND_FONT (item);
+ bse_sound_font_unload (sound_font);
+ return TRUE;
+}
+
+static void
+bse_sound_font_repo_prepare (BseSource *source)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (source);
+ int i, channels_required = 0;
+ for (i = 0; i < sfrepo->n_oscs; i++)
+ {
+ if (sfrepo->oscs[i])
+ sfrepo->channel_map[i] = channels_required++;
+ }
+ int mix_freq = bse_engine_sample_freq();
+ if (sfrepo->n_fluid_channels != channels_required || sfrepo->fluid_mix_freq != mix_freq)
+ {
+ for (i = channels_required; i < sfrepo->n_fluid_channels; i++) // n_fluid_channels > channels_required
+ {
+ g_free (sfrepo->channel_values_left[i]);
+ g_free (sfrepo->channel_values_right[i]);
+ }
+ sfrepo->channel_values_left = (float **)g_realloc (sfrepo->channel_values_left, sizeof (float *) *
channels_required);
+ sfrepo->channel_values_right = (float **)g_realloc (sfrepo->channel_values_right, sizeof (float *) *
channels_required);
+ sfrepo->n_silence_samples = (gint *) g_realloc (sfrepo->n_silence_samples, sizeof (gint) *
channels_required);
+ for (i = sfrepo->n_fluid_channels; i < channels_required; i++) // n_fluid_channels < channels_required
+ {
+ sfrepo->channel_values_left[i] = g_new0 (float, BSE_STREAM_MAX_VALUES);
+ sfrepo->channel_values_right[i] = g_new0 (float, BSE_STREAM_MAX_VALUES);
+ sfrepo->n_silence_samples[i] = 0;
+ }
+ sfrepo->n_fluid_channels = channels_required;
+ sfrepo->fluid_mix_freq = mix_freq;
+
+ fluid_settings_setnum (sfrepo->fluid_settings, "synth.sample-rate", mix_freq);
+ fluid_settings_setint (sfrepo->fluid_settings, "synth.midi-channels", channels_required);
+ fluid_settings_setint (sfrepo->fluid_settings, "synth.audio-channels", channels_required);
+ fluid_settings_setint (sfrepo->fluid_settings, "synth.audio-groups", channels_required);
+ fluid_settings_setstr (sfrepo->fluid_settings, "synth.reverb.active", "no");
+ fluid_settings_setstr (sfrepo->fluid_settings, "synth.chorus.active", "no");
+
+ bse_sound_font_repo_forall_items (BSE_CONTAINER (sfrepo), unload_sound_font, sfrepo);
+ if (sfrepo->fluid_synth)
+ delete_fluid_synth (sfrepo->fluid_synth);
+
+ sfrepo->fluid_synth = new_fluid_synth (sfrepo->fluid_settings);
+ bse_sound_font_repo_forall_items (BSE_CONTAINER (sfrepo), reload_sound_font, sfrepo);
+ }
+
+ /* chain parent class' handler */
+ BSE_SOURCE_CLASS (parent_class)->prepare (source);
+}
+
+static void
+bse_sound_font_repo_release_children (BseContainer *container)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
+
+ while (sfrepo->sound_fonts)
+ bse_container_remove_item (container, sfrepo->sound_fonts->data);
+
+ /* chain parent class' handler */
+ BSE_CONTAINER_CLASS (parent_class)->release_children (container);
+}
+
+static void
+bse_sound_font_repo_dispose (GObject *object)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (object);
+ int i;
+
+ bse_sound_font_repo_forall_items (BSE_CONTAINER (sfrepo), unload_sound_font, sfrepo);
+
+ if (sfrepo->fluid_synth)
+ {
+ delete_fluid_synth (sfrepo->fluid_synth);
+ sfrepo->fluid_synth = NULL;
+ }
+ if (sfrepo->fluid_settings)
+ {
+ delete_fluid_settings (sfrepo->fluid_settings);
+ sfrepo->fluid_settings = NULL;
+ }
+ g_free (sfrepo->channel_map);
+ sfrepo->channel_map = NULL;
+ g_free (sfrepo->oscs);
+ sfrepo->oscs = NULL;
+ for (i = 0; i < sfrepo->n_fluid_channels; i++)
+ {
+ g_free (sfrepo->channel_values_left[i]);
+ g_free (sfrepo->channel_values_right[i]);
+ }
+ sfrepo->n_fluid_channels = 0;
+ g_free (sfrepo->channel_values_left);
+ sfrepo->channel_values_left = NULL;
+ g_free (sfrepo->channel_values_right);
+ sfrepo->channel_values_right = NULL;
+ g_free (sfrepo->n_silence_samples);
+ sfrepo->n_silence_samples = NULL;
+
+ if (sfrepo->fluid_events != NULL)
+ g_warning (G_STRLOC ": fluid event queue should be empty in dispose");
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+bse_sound_font_repo_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (object);
+ switch (param_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (sfrepo, param_id, pspec);
+ break;
+ }
+}
+
+static void
+bse_sound_font_repo_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (object);
+ switch (param_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (sfrepo, param_id, pspec);
+ break;
+ }
+}
+
+static void
+bse_sound_font_repo_add_item (BseContainer *container,
+ BseItem *item)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
+
+ if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT))
+ sfrepo->sound_fonts = g_list_append (sfrepo->sound_fonts, item);
+ else
+ g_warning ("BseSoundFontRepo: cannot hold non-sound-font item type `%s'",
+ BSE_OBJECT_TYPE_NAME (item));
+
+ /* chain parent class' add_item handler */
+ BSE_CONTAINER_CLASS (parent_class)->add_item (container, item);
+}
+
+static void
+bse_sound_font_repo_forall_items (BseContainer *container,
+ BseForallItemsFunc func,
+ gpointer data)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
+ GList *list;
+
+ list = sfrepo->sound_fonts;
+ while (list)
+ {
+ BseItem *item;
+
+ item = list->data;
+ list = list->next;
+ if (!func (item, data))
+ return;
+ }
+}
+
+static void
+bse_sound_font_repo_remove_item (BseContainer *container,
+ BseItem *item)
+{
+ BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
+
+ if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT))
+ sfrepo->sound_fonts = g_list_remove (sfrepo->sound_fonts, item);
+ else
+ g_warning ("BseSoundFontRepo: cannot hold non-sound-font item type `%s'",
+ BSE_OBJECT_TYPE_NAME (item));
+
+ /* chain parent class' remove_item handler */
+ BSE_CONTAINER_CLASS (parent_class)->remove_item (container, item);
+}
+
+static gboolean
+gather_presets (BseItem *item,
+ gpointer items)
+{
+ if (BSE_IS_SOUND_FONT (item) || BSE_IS_SOUND_FONT_REPO (item))
+ bse_container_forall_items (BSE_CONTAINER (item), gather_presets, items);
+ else if (BSE_IS_SOUND_FONT_PRESET (item))
+ bse_item_seq_append (items, item);
+ else
+ g_warning ("Searching for sound font presets, an unexpected `%s' item was found", BSE_OBJECT_TYPE_NAME
(item));
+ return TRUE;
+}
+
+void
+bse_sound_font_repo_list_all_presets (BseSoundFontRepo *sfrepo,
+ BseItemSeq *items)
+{
+ gather_presets (BSE_ITEM (sfrepo), items);
+}
+
+fluid_synth_t *
+bse_sound_font_repo_lock_fluid_synth (BseSoundFontRepo *sfrepo)
+{
+ sfi_mutex_lock (&sfrepo->fluid_synth_mutex);
+ return sfrepo->fluid_synth;
+}
+
+void
+bse_sound_font_repo_unlock_fluid_synth (BseSoundFontRepo *sfrepo)
+{
+ sfi_mutex_unlock (&sfrepo->fluid_synth_mutex);
+}
+
+int
+bse_sound_font_repo_add_osc (BseSoundFontRepo *sfrepo,
+ BseSoundFontOsc *osc)
+{
+ int i;
+ for (i = 0; i < sfrepo->n_oscs; i++)
+ {
+ if (sfrepo->oscs[i] == 0)
+ {
+ sfrepo->oscs[i] = osc;
+ return i;
+ }
+ }
+ sfrepo->oscs = (BseSoundFontOsc **)g_realloc (sfrepo->oscs, sizeof (BseSoundFontOsc *) * (i + 1));
+ sfrepo->oscs[i] = osc;
+ sfrepo->channel_map = g_realloc (sfrepo->channel_map, sizeof (guint) * (i + 1));
+ return sfrepo->n_oscs++;
+}
+
+void
+bse_sound_font_repo_remove_osc (BseSoundFontRepo *sfrepo,
+ int osc_id)
+{
+ g_return_if_fail (osc_id >= 0 && osc_id < sfrepo->n_oscs);
+
+ sfrepo->oscs[osc_id] = 0;
+}
diff --git a/bse/bsesoundfontrepo.h b/bse/bsesoundfontrepo.h
new file mode 100644
index 0000000..312d624
--- /dev/null
+++ b/bse/bsesoundfontrepo.h
@@ -0,0 +1,94 @@
+/* BSE - Bedevilled Sound Engine
+ * Copyright (C) 1996-1999, 2000-2003 Tim Janik
+ * Copyright (C) 2009 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#ifndef __BSE_SOUND_FONT_REPO_H__
+#define __BSE_SOUND_FONT_REPO_H__
+
+#include <bse/bsesuper.h>
+#include <fluidsynth.h>
+#include <bse/bsesoundfontosc.h>
+#include <bse/bseengine.h>
+
+
+G_BEGIN_DECLS
+
+
+/* --- object type macros --- */
+#define BSE_TYPE_SOUND_FONT_REPO (BSE_TYPE_ID (BseSoundFontRepo))
+#define BSE_SOUND_FONT_REPO(object) (G_TYPE_CHECK_INSTANCE_CAST ((object),
BSE_TYPE_SOUND_FONT_REPO, BseSoundFontRepo))
+#define BSE_SOUND_FONT_REPO_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), BSE_TYPE_SOUND_FONT_REPO,
BseSoundFontRepoClass))
+#define BSE_IS_SOUND_FONT_REPO(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object),
BSE_TYPE_SOUND_FONT_REPO))
+#define BSE_IS_SOUND_FONT_REPO_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), BSE_TYPE_SOUND_FONT_REPO))
+#define BSE_SOUND_FONT_REPO_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object),
BSE_TYPE_SOUND_FONT_REPO, BseSoundFontRepoClass))
+
+
+/* --- BseSoundFontRepo object --- */
+#define BSE_FLUID_SYNTH_PROGRAM_SELECT -1
+typedef struct _BseFluidEvent BseFluidEvent;
+struct _BseFluidEvent
+{
+ guint64 tick_stamp;
+ int channel;
+ int command;
+ int arg1;
+ int arg2;
+ int sfont_id; /* required for program selection only */
+};
+struct _BseSoundFontRepo
+{
+ BseSuper parent_object;
+
+ BirnetMutex fluid_synth_mutex;
+ fluid_settings_t *fluid_settings;
+ fluid_synth_t *fluid_synth;
+ SfiRing *fluid_events;
+ guint fluid_mix_freq;
+
+ guint n_fluid_channels;
+ float **channel_values_left; /* [0..n_fluid_channels-1] */
+ float **channel_values_right; /* [0..n_fluid_channels-1] */
+ guint64 channel_values_tick_stamp;
+ gint *n_silence_samples; /* [0..n_fluid_channels-1] */
+
+ guint n_oscs;
+ BseSoundFontOsc **oscs; /* [0..n_oscs-1] */
+ guint *channel_map; /* [0..n_oscs-1] */
+
+ int n_channel_oscs_active; /* SoundFontOscs with an active module in the engine thread
*/
+
+ GList *sound_fonts;
+};
+
+struct _BseSoundFontRepoClass
+{
+ BseSuperClass parent_class;
+};
+
+
+/* --- prototypes --- */
+void bse_sound_font_repo_list_all_presets (BseSoundFontRepo *sfrepo,
+ BseItemSeq *items);
+fluid_synth_t *bse_sound_font_repo_lock_fluid_synth (BseSoundFontRepo *sfrepo);
+void bse_sound_font_repo_unlock_fluid_synth (BseSoundFontRepo *sfrepo);
+int bse_sound_font_repo_add_osc (BseSoundFontRepo *sfrepo,
+ BseSoundFontOsc *osc);
+void bse_sound_font_repo_remove_osc (BseSoundFontRepo *sfrepo,
+ int osc_id);
+
+G_END_DECLS
+
+#endif /* __BSE_SOUND_FONT_REPO_H__ */
diff --git a/bse/bsesoundfontrepo.proc b/bse/bsesoundfontrepo.proc
new file mode 100644
index 0000000..8281837
--- /dev/null
+++ b/bse/bsesoundfontrepo.proc
@@ -0,0 +1,155 @@
+/* BSE - Bedevilled Sound Engine -*-mode: c;-*-
+ * Copyright (C) 2000-2003 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#include <bse/bseplugin.h>
+#include <bse/bseprocedure.h>
+#include <bse/bsesoundfontrepo.h>
+#include <bse/bsesoundfont.h>
+#include <bse/bseloader.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+/* --- auxlillary functions --- */
+static BseErrorType
+load_file (BseSoundFontRepo *sfrepo,
+ const gchar *file_name,
+ BseSoundFont **sound_font_p)
+{
+ gchar *fname = g_path_get_basename (file_name);
+ BseSoundFont *sound_font = g_object_new (BSE_TYPE_SOUND_FONT, "uname", fname, NULL);
+ g_free (fname);
+ bse_container_add_item (BSE_CONTAINER (sfrepo), BSE_ITEM (sound_font));
+
+ BseStorageBlob *blob = bse_storage_blob_new_from_file (file_name, FALSE);
+ BseErrorType error = bse_sound_font_load_blob (sound_font, blob, TRUE);
+ bse_storage_blob_unref (blob);
+ if (error == BSE_ERROR_NONE)
+ {
+ *sound_font_p = sound_font;
+ }
+ else
+ {
+ bse_container_remove_item (BSE_CONTAINER (sfrepo), BSE_ITEM (sound_font));
+ *sound_font_p = NULL;
+ }
+ g_object_unref (sound_font);
+ return error;
+}
+
+/* --- procedures --- */
+AUTHORS = "Tim Janik <timj gtk org>";
+LICENSE = "GNU Lesser General Public License";
+
+
+METHOD (BseSoundFontRepo, load-file) {
+ HELP = "Load sound font from file";
+ IN = bse_param_spec_object ("sound_font_repo", "Sound Font Repo", NULL,
+ BSE_TYPE_SOUND_FONT_REPO, SFI_PARAM_STANDARD);
+ IN = sfi_pspec_string ("file_name", "File Name", "The file to import sound fonts from",
+ NULL, SFI_PARAM_STANDARD);
+ OUT = bse_param_spec_genum ("error", "Error", NULL,
+ BSE_TYPE_ERROR_TYPE, BSE_ERROR_NONE,
+ SFI_PARAM_STANDARD);
+}
+BODY (BseProcedureClass *proc,
+ const GValue *in_values,
+ GValue *out_values)
+{
+ /* extract parameter values */
+ BseSoundFontRepo *self = (BseSoundFontRepo*) bse_value_get_object (in_values++);
+ gchar *file_name = sfi_value_get_string (in_values++);
+ BseUndoStack *ustack;
+ BseErrorType error;
+ BseSoundFont *sound_font;
+
+ /* check parameters */
+ if (!BSE_IS_SOUND_FONT_REPO (self) || !file_name)
+ return BSE_ERROR_PROC_PARAM_INVAL;
+
+ if (BSE_SOURCE_PREPARED (self))
+ {
+ /* In theory, its possible to allow loading sound fonts while
+ * the project is playing; in practice, the sound font repo
+ * lock would be locked for a very long time, which would stall
+ * the audio production ...
+ */
+ error = BSE_ERROR_SOURCE_BUSY;
+ }
+ else
+ {
+ ustack = bse_item_undo_open (self, "load-sound-font");
+ error = load_file (self, file_name, &sound_font);
+ if (sound_font)
+ bse_item_push_undo_proc (self, "remove-sound-font", sound_font);
+ bse_item_undo_close (ustack);
+ }
+
+ /* set output parameters */
+ g_value_set_enum (out_values++, error);
+
+ return BSE_ERROR_NONE;
+}
+
+METHOD (BseSoundFontRepo, remove-sound-font) {
+ HELP = "Remove a sound font from repository";
+ IN = bse_param_spec_object ("sound_font_repo", "Sound Font Repo", NULL,
+ BSE_TYPE_SOUND_FONT_REPO, SFI_PARAM_STANDARD);
+ IN = bse_param_spec_object ("sound_font", "Sound Font", NULL,
+ BSE_TYPE_SOUND_FONT, SFI_PARAM_STANDARD);
+} BODY (BseProcedureClass *proc,
+ const GValue *in_values,
+ GValue *out_values)
+{
+ /* extract parameter values */
+ BseSoundFontRepo *self = (BseSoundFontRepo*) bse_value_get_object (in_values++);
+ BseItem *child = (BseItem*) bse_value_get_object (in_values++);
+ BseUndoStack *ustack;
+ BseErrorType error;
+
+ /* check parameters */
+ if (!BSE_IS_SOUND_FONT_REPO (self) || !BSE_IS_SOUND_FONT (child) ||
+ child->parent != BSE_ITEM (self))
+ return BSE_ERROR_PROC_PARAM_INVAL;
+
+ if (BSE_SOURCE_PREPARED (self))
+ {
+ /* Don't allow unloading sound fonts which could be required by engine
+ * modules in the DSP thread currently producing audio output.
+ */
+ error = BSE_ERROR_SOURCE_BUSY;
+ }
+ else
+ {
+ /* action */
+ ustack = bse_item_undo_open (self, "remove-sound-font %s", bse_object_debug_name (child));
+ /* remove object references */
+ bse_container_uncross_undoable (BSE_CONTAINER (self), child);
+ /* how to get rid of the item once backed up */
+ bse_item_push_redo_proc (self, "remove-sound-font", child);
+ /* remove (without redo queueing) */
+ bse_container_remove_backedup (BSE_CONTAINER (self), child, ustack);
+ /* done */
+ bse_item_undo_close (ustack);
+
+ error = BSE_ERROR_NONE;
+ }
+
+ return error;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]