Imported Upstream version 0.2.4
[platform/upstream/remix.git] / src / libremix / remix_context.c
1 /*
2  * libremix -- An audio mixing and sequencing library.
3  *
4  * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
5  * Organisation (CSIRO), Australia.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 /*
24  * RemixContext: REMIX core context.
25  *
26  * Conrad Parker <conrad@metadecks.org>, August 2001
27  */
28
29 #include <string.h>
30
31 #define __REMIX__
32 #include "remix.h"
33
34 static void
35 remix_plugin_destroy (RemixEnv * env, RemixPlugin * plugin)
36 {
37   if (plugin->destroy) {
38     plugin->destroy (env, plugin);
39   }
40 }
41
42 static void
43 remix_context_destroy (RemixEnv * env)
44 {
45   RemixContext * ctx = env->context;
46   RemixWorld * world = env->world;
47
48   world->purging = 1;
49
50   world->plugins = cd_list_destroy_with (env, world->plugins, remix_plugin_destroy);
51   remix_plugin_defaults_unload (env);
52
53   //world->bases = cd_list_destroy_with (env, world->bases, remix_destroy);
54
55   remix_channelset_defaults_destroy (env);
56   remix_free (ctx);
57   remix_free (world);
58 }
59
60 static RemixEnv *
61 remix_add_thread_context (RemixContext * ctx, RemixWorld * world)
62 {
63   RemixEnv * env = remix_malloc (sizeof (struct _RemixThreadContext));
64   env->context = ctx;
65   env->world = world;
66   world->refcount++;
67   return env;
68 }
69
70 RemixContext *
71 _remix_context_copy (RemixEnv * env, RemixContext * dest)
72 {
73   RemixContext * ctx = env->context;
74
75   if (dest == RemixNone) {
76     remix_set_error (env, REMIX_ERROR_NOENTITY);
77     return RemixNone;
78   }
79
80   dest->samplerate = ctx->samplerate;
81   dest->tempo = ctx->tempo;
82   dest->mixlength = ctx->mixlength;
83   dest->channels = cd_set_clone_keys (env, ctx->channels);
84
85   return dest;
86 }
87
88 /*
89  * _remix_context_merge (env, dest)
90  *
91  * Merges the context of env into context 'dest'. Copies over the samplerate
92  * and tempo, and expands the mixlength and channels if they are greater in
93  * 'env's context than in 'dest'.
94  */
95 RemixContext *
96 _remix_context_merge (RemixEnv * env, RemixContext * dest)
97 {
98   RemixContext * ctx = env->context;
99   CDSet * s;
100   CDScalar k;
101
102   if (dest == RemixNone) {
103     remix_set_error (env, REMIX_ERROR_NOENTITY);
104     return RemixNone;
105   }
106
107   dest->samplerate = ctx->samplerate;
108   dest->tempo = ctx->tempo;
109
110   if (ctx->mixlength > dest->mixlength)
111     dest->mixlength = ctx->mixlength;
112
113   for (s = ctx->channels; s; s = s->next) {
114     k = cd_set_find (env, dest->channels, s->key);
115     if (k.s_pointer == NULL)
116       dest->channels = cd_set_insert (env, dest->channels, s->key,
117                                       CD_POINTER(NULL));
118   }
119
120   return dest;
121 }
122
123 /*
124  * remix_init ()
125  */
126 RemixEnv *
127 remix_init (void)
128 {
129   RemixEnv * env;
130   RemixWorld * world =
131     (RemixWorld *) remix_malloc (sizeof (struct _RemixWorld));
132   RemixContext * ctx =
133     (RemixContext *) remix_malloc (sizeof (struct _RemixContext));
134
135   world->refcount = 0;
136   world->plugins = cd_list_new (ctx);
137   world->bases = cd_list_new (ctx);
138   world->purging = FALSE;
139
140   ctx->mixlength = REMIX_DEFAULT_MIXLENGTH;
141   ctx->samplerate = REMIX_DEFAULT_SAMPLERATE;
142   ctx->tempo = REMIX_DEFAULT_TEMPO;
143
144   env = remix_add_thread_context (ctx, world);
145   remix_channelset_defaults_initialise (env);
146   ctx->channels = REMIX_MONO;
147
148   remix_plugin_defaults_initialise (env);
149
150   return env;
151 }
152
153 /*
154  * remix_init_clone ()
155  */
156 RemixEnv *
157 remix_init_clone (RemixEnv * env)
158 {
159   RemixEnv * new_env = remix_add_thread_context (env->context, env->world);
160   return new_env;
161 }
162
163 void
164 remix_purge (RemixEnv * env)
165 {
166   RemixWorld * world = env->world;
167   world->refcount--;
168   if (world->refcount <= 0) {
169     remix_context_destroy (env);
170   }
171   remix_free (env);
172 }
173
174 RemixError
175 remix_set_error (RemixEnv * env, RemixError error)
176 {
177   RemixError old = env->last_error;
178   env->last_error = error;
179   return old;
180 }
181
182 RemixError
183 remix_last_error (RemixEnv * env)
184 {
185   return env->last_error;
186 }
187
188 RemixCount
189 remix_set_mixlength (RemixEnv * env, RemixCount mixlength)
190 {
191   RemixContext * ctx = env->context;
192   RemixCount old = ctx->mixlength;
193   ctx->mixlength = mixlength;
194   return old;
195 }
196
197 RemixCount
198 remix_get_mixlength (RemixEnv * env)
199 {
200   RemixContext * ctx = env->context;
201   return ctx->mixlength;
202 }
203
204 RemixSamplerate
205 remix_set_samplerate (RemixEnv * env, RemixSamplerate samplerate)
206 {
207   RemixContext * ctx = env->context;
208   RemixSamplerate old = ctx->samplerate;
209   ctx->samplerate = samplerate;
210   return old;
211 }
212
213 RemixSamplerate
214 remix_get_samplerate (RemixEnv * env)
215 {
216   RemixContext * ctx = env->context;
217   return ctx->samplerate;
218 }
219
220 RemixTempo
221 remix_set_tempo (RemixEnv * env, RemixTempo tempo)
222 {
223   RemixContext * ctx = env->context;
224   RemixTempo old = ctx->tempo;
225   ctx->tempo = tempo;
226   return old;
227 }
228
229 RemixTempo
230 remix_get_tempo (RemixEnv * env)
231 {
232   RemixContext * ctx = env->context;
233   return ctx->tempo;
234 }
235
236 CDSet *
237 remix_set_channels (RemixEnv * env,  CDSet * channels)
238 {
239   RemixContext * ctx = env->context;
240   CDSet * old = ctx->channels;
241   ctx->channels = cd_set_clone_keys (env, channels);
242   return old;
243 }
244
245 CDSet *
246 remix_get_channels (RemixEnv * env)
247 {
248   RemixContext * ctx = env->context;
249   return ctx->channels;
250 }
251
252 RemixEnv *
253 _remix_register_plugin (RemixEnv * env, RemixPlugin * plugin)
254 {
255   RemixWorld * world = env->world;
256   remix_dprintf ("[_remix_register_plugin] REGISTERING %s\n",
257                  plugin->metatext ? plugin->metatext->identifier : "(\?\?\?)");
258   world->plugins = cd_list_append (env, world->plugins, CD_POINTER(plugin));
259   return env;
260 }
261
262 RemixEnv *
263 _remix_unregister_plugin (RemixEnv * env, RemixPlugin * plugin)
264 {
265   RemixWorld * world = env->world;
266   if (world->purging) return env;
267
268   world->plugins = cd_list_remove (env, world->plugins, CD_TYPE_POINTER,
269                                    CD_POINTER(plugin));
270   return env;
271 }
272
273 RemixEnv *
274 _remix_register_base (RemixEnv * env, RemixBase * base)
275 {
276   RemixWorld * world = env->world;
277   world->bases = cd_list_append (env, world->bases, CD_POINTER(base));
278   return env;
279 }
280
281 RemixEnv *
282 _remix_unregister_base (RemixEnv * env, RemixBase * base)
283 {
284   RemixWorld * world = env->world;
285   if (world->purging) return env;
286
287   world->bases = cd_list_remove (env, world->bases, CD_TYPE_POINTER,
288                                  CD_POINTER(base));
289   return env;
290 }
291
292 static int
293 plugin_id_eq (RemixEnv * env, RemixPlugin * plugin, char * identifier)
294 {
295   if (plugin == RemixNone) return FALSE;
296   if (plugin->metatext == RemixNone) return FALSE;
297   return !(strcmp(plugin->metatext->identifier, identifier));
298 }
299
300 RemixPlugin *
301 remix_find_plugin (RemixEnv * env, char * identifier)
302 {
303   RemixWorld * world = env->world;
304   CDList * l = cd_list_find_first (env, world->plugins, CD_TYPE_POINTER,
305                                    (CDCmpFunc)plugin_id_eq,
306                                    CD_POINTER(identifier));
307
308   if (l == RemixNone) return RemixNone;
309   return (RemixPlugin *)l->data.s_pointer;
310 }