Merge pull request #1 from atsampson/master
[calfbox.git] / sfzloader.c
blob1cad1a8b8d21e4a871493f9d7430f0ca479717e5
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "sampler.h"
20 #include "sfzparser.h"
22 #define DUMP_LAYER_ATTRIBS 0
24 struct sfz_load_state
26 struct sampler_module *m;
27 const char *filename;
28 struct sampler_program *program;
29 struct sampler_layer *group;
30 struct sampler_layer *region;
31 gboolean is_control;
32 GError **error;
35 static void load_sfz_end_region(struct sfz_parser_client *client)
37 struct sfz_load_state *ls = client->user_data;
38 // printf("-- copy current region to the list of layers\n");
39 struct sampler_layer *l = ls->region;
40 sampler_layer_data_finalize(&l->data, l->parent_group ? &l->parent_group->data : NULL, ls->program);
41 sampler_layer_reset_switches(l, ls->m);
42 sampler_layer_update(l);
43 sampler_program_add_layer(ls->program, ls->region);
45 ls->region = NULL;
48 static void end_token(struct sfz_parser_client *client)
50 struct sfz_load_state *ls = client->user_data;
51 #if DUMP_LAYER_ATTRIBS
52 if (ls->group)
54 fprintf(stdout, "<group>");
55 sampler_layer_dump(&ls->group, stdout);
57 if (ls->region)
59 fprintf(stdout, "<region>");
60 sampler_layer_dump(&ls->region, stdout);
62 #endif
63 if (ls->region)
64 load_sfz_end_region(client);
65 ls->is_control = FALSE;
68 static gboolean load_sfz_group(struct sfz_parser_client *client)
70 struct sfz_load_state *ls = client->user_data;
71 // printf("-- start group\n");
72 ls->group = sampler_layer_new(ls->m, ls->program, NULL);
73 sampler_program_add_group(ls->program, ls->group);
74 return TRUE;
77 static gboolean load_sfz_region(struct sfz_parser_client *client)
79 struct sfz_load_state *ls = client->user_data;
81 ls->region = sampler_layer_new(ls->m, ls->program, ls->group);
82 // g_warning("-- start region");
83 return TRUE;
86 static gboolean load_sfz_key_value(struct sfz_parser_client *client, const char *key, const char *value)
88 struct sfz_load_state *ls = client->user_data;
90 if (ls->is_control)
92 if (!strncmp(key, "set_cc", 6))
94 int ctrl = atoi(key + 6);
95 int val = atoi(value);
96 if (ctrl >= 0 && ctrl <= 119 && val >=0 && val <= 127)
97 sampler_program_add_controller_init(ls->program, ctrl, val);
98 else
99 g_warning("Invalid CC initialisation: %s=%s", key, value);
101 else
102 g_warning("Unrecognized SFZ key in control section: %s", key);
103 return TRUE;
106 struct sampler_layer *l = ls->region ? ls->region : ls->group;
107 if (!ls->region && !ls->group)
109 g_warning("Cannot use parameter '%s' outside of region or group", key);
110 return TRUE;
113 if (!sampler_layer_apply_param(l, key, value, ls->error))
114 return FALSE;
116 return TRUE;
119 static gboolean handle_token(struct sfz_parser_client *client, const char *token, GError **error)
121 struct sfz_load_state *ls = client->user_data;
122 end_token(client);
124 if (!strcmp(token, "region"))
125 return load_sfz_region(client);
127 if (!strcmp(token, "group"))
128 return load_sfz_group(client);
130 if (!strcmp(token, "control"))
132 ls->is_control = TRUE;
133 return TRUE;
136 g_set_error(error, CBOX_SFZPARSER_ERROR, CBOX_SFZ_PARSER_ERROR_INVALID_HEADER, "Unexpected header <%s>", token);
137 return FALSE;
140 gboolean sampler_module_load_program_sfz(struct sampler_module *m, struct sampler_program *prg, const char *sfz, int is_from_string, GError **error)
142 struct sfz_load_state ls = { .group = prg->default_group, .m = m, .filename = sfz, .region = NULL, .error = error, .program = prg, .is_control = FALSE };
143 struct sfz_parser_client c = { .user_data = &ls, .token = handle_token, .key_value = load_sfz_key_value };
144 g_clear_error(error);
146 gboolean status;
147 if (is_from_string)
148 status = load_sfz_from_string(sfz, strlen(sfz), &c, error);
149 else
150 status = load_sfz(sfz, prg->tarfile, &c, error);
151 if (!status)
153 if (ls.region)
154 CBOX_DELETE(ls.region);
155 return FALSE;
158 end_token(&c);
160 prg->all_layers = g_slist_reverse(prg->all_layers);
161 sampler_program_update_layers(prg);
162 return TRUE;