missing commit in generator.h
[galan.git] / src / generator.c
blob4e06c7edc291e562685d4b7ee93c2a993a292fdf
1 /* gAlan - Graphical Audio Language
2 * Copyright (C) 1999 Tony Garnock-Jones
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdio.h>
23 #include <gdk/gdk.h>
24 #include <gtk/gtk.h>
26 #include "global.h"
27 #include "generator.h"
28 #include "control.h"
29 #include "msgbox.h"
31 #include "galan_jack.h"
33 /**
34 * \brief This is a hash mapping from string -> GeneratorClass
36 * This is used when a Generator is unpickled to find the GeneratorClass from the name tag.
39 PRIVATE GHashTable *generatorclasses = NULL;
41 /**
42 * \brief This queue contains EventLinks which should be added to the system.
45 PRIVATE GAsyncQueue *gen_link_queue;
46 /**
47 * \brief This queue contains EventLinks which should be removed from the system.
50 PRIVATE GAsyncQueue *gen_unlink_queue;
52 /**
53 * \brief This queue contains Generator s which shall be killed.
54 * These will be passed to a free thread but at the moment will only use safe_free.
57 PRIVATE GAsyncQueue *gen_kill_queue;
58 PRIVATE GAsyncQueue *gen_kill_queue_stage2;
60 PRIVATE GThread *kill_thread;
62 PRIVATE int gen_samplerate = 44100;
64 PUBLIC int gen_get_sample_rate( void ) {
65 return gen_samplerate;
68 /**
69 * \brief Initialize an AEvent.
71 * Fills in the fields of an AEvent.
73 * \param e AEvent to fill.
74 * \param kind kind of the AEvent.
75 * \param src Where the event comes from.
76 * \param src_q The Connector number the AEvent comes from.
77 * \param dst The Generator which is to receive the AEvent.
78 * \param dst_q The Connector number which receives the event.
79 * \param time The SAMPLETIME when the event shall be processed.
83 PUBLIC void gen_init_aevent(AEvent *e, AEventKind kind,
84 Generator *src, int src_q,
85 Generator *dst, int dst_q, SAMPLETIME time) {
86 g_return_if_fail(e != NULL);
88 e->kind = kind;
89 e->src = src;
90 e->src_q = src_q;
91 e->dst = dst;
92 e->dst_q = dst_q;
93 e->time = time;
96 /**
97 * \brief Registers a new GeneratorClass with the system.
99 * \param name The Name Tag of the GenratorClass (This must be unique as it is used to find the GenratorClass on load)
100 * \param prefer If a GenratorClass with the same name exists should this be overwritten.
101 * \param count_event_in Number of Input AEvents the GenratorClass will have.
102 * \param count_event_out Number of Output AEvents the GenratorClass will have.
103 * \param input_sigs An Array of InputSignalDescriptor describing the Input Signals. (Can be NULL)
104 * \param output_sigs An Array of OutputSignalDescriptor describing the Output Signals. (Can be NULL)
105 * \param controls An Array of ControlDescriptor describing the Controls of the GenratorClass. (Can bu NULL)
106 * \param initializer The Constructor Function for the GeneratorClass specific initialisation. (Can be NULL)
107 * \param destructor The Destructor Function for the GeneratorClass specific destruction. (Can be NULL)
108 * \param unpickle_instance Unpickle Function
109 * \param pickle_instance Pickle Function
113 PUBLIC GeneratorClass *gen_new_generatorclass(const char *name, gboolean prefer,
114 gint count_event_in, gint count_event_out,
115 InputSignalDescriptor *input_sigs,
116 OutputSignalDescriptor *output_sigs,
117 ControlDescriptor *controls,
118 int (*initializer)(Generator *),
119 void (*destructor)(Generator *),
120 AGenerator_pickle_t unpickle_instance,
121 AGenerator_pickle_t pickle_instance) {
123 return
124 gen_new_generatorclass_with_different_tag( name, name, prefer,
125 count_event_in, count_event_out,
126 input_sigs,
127 output_sigs,
128 controls,
129 initializer,
130 destructor,
131 unpickle_instance,
132 pickle_instance );
135 * \brief Registers a new GeneratorClass with the system.
137 * \param name The Name of the GenratorClass which is presented to the humen (you know... those who cant remeber numbers)
138 * \param tag The Tag of the GenratorClass (This must be unique as it is used to find the GenratorClass on load)
139 * \param prefer If a GenratorClass with the same name exists should this be overwritten.
140 * \param count_event_in Number of Input AEvents the GenratorClass will have.
141 * \param count_event_out Number of Output AEvents the GenratorClass will have.
142 * \param input_sigs An Array of InputSignalDescriptor describing the Input Signals. (Can be NULL)
143 * \param output_sigs An Array of OutputSignalDescriptor describing the Output Signals. (Can be NULL)
144 * \param controls An Array of ControlDescriptor describing the Controls of the GenratorClass. (Can bu NULL)
145 * \param initializer The Constructor Function for the GeneratorClass specific initialisation. (Can be NULL)
146 * \param destructor The Destructor Function for the GeneratorClass specific destruction. (Can be NULL)
147 * \param unpickle_instance Unpickle Function
148 * \param pickle_instance Pickle Function
152 PUBLIC GeneratorClass *gen_new_generatorclass_with_different_tag(const char *name, const char *tag, gboolean prefer,
153 gint count_event_in, gint count_event_out,
154 InputSignalDescriptor *input_sigs,
155 OutputSignalDescriptor *output_sigs,
156 ControlDescriptor *controls,
157 int (*initializer)(Generator *),
158 void (*destructor)(Generator *),
159 AGenerator_pickle_t unpickle_instance,
160 AGenerator_pickle_t pickle_instance) {
162 GeneratorClass *k = safe_malloc(sizeof(GeneratorClass));
164 k->name = safe_string_dup(name);
165 k->tag = safe_string_dup(tag);
167 k->in_count = count_event_in;
168 k->out_count = count_event_out;
170 k->in_sigs = input_sigs;
171 k->out_sigs = output_sigs;
172 k->controls = controls;
174 if (input_sigs == NULL)
175 k->in_sig_count = 0;
176 else
177 for (k->in_sig_count = 0;
178 k->in_sigs[k->in_sig_count].name != NULL;
179 k->in_sig_count++) ;
181 if (output_sigs == NULL)
182 k->out_sig_count = 0;
183 else
184 for (k->out_sig_count = 0;
185 k->out_sigs[k->out_sig_count].name != NULL;
186 k->out_sig_count++) ;
188 if (controls == NULL)
189 k->numcontrols = 0;
190 else
191 for (k->numcontrols = 0;
192 k->controls[k->numcontrols].kind != CONTROL_KIND_NONE;
193 k->numcontrols++) ;
195 if( count_event_in > 0 ) {
196 k->in_names = safe_calloc(count_event_in, sizeof(char *));
197 k->in_handlers = safe_calloc(count_event_in, sizeof(AEvent_handler_t));
199 if( count_event_out > 0 )
200 k->out_names = safe_calloc(count_event_out, sizeof(char *));
202 k->initialize_instance = initializer;
203 k->destroy_instance = destructor;
204 k->unpickle_instance = unpickle_instance;
205 k->pickle_instance = pickle_instance;
207 /* Only insert into hash table if this name is not already taken, or if we are preferred. */
209 GeneratorClass *oldk = g_hash_table_lookup(generatorclasses, k->tag);
211 if (oldk == NULL)
212 g_hash_table_insert(generatorclasses, k->tag, k);
213 else if (prefer) {
214 g_hash_table_remove(generatorclasses, k->tag);
215 g_hash_table_insert(generatorclasses, k->tag, k);
219 return k;
223 * \brief Free Memory used by a GeneratorClass
225 * If you have some Instances of this GenratorClass in your Memory and kill the Class
226 * expect Segfaults.
228 * \param g GenratorClass to free.
231 PUBLIC void gen_kill_generatorclass(GeneratorClass *g) {
232 int i;
234 free(g->name);
235 free(g->tag);
237 for (i = 0; i < g->in_count; i++)
238 if (g->in_names[i] != NULL)
239 free(g->in_names[i]);
240 free(g->in_names);
241 free(g->in_handlers);
243 for (i = 0; i < g->out_count; i++)
244 if (g->out_names[i] != NULL)
245 free(g->out_names[i]);
246 free(g->out_names);
248 free(g);
252 * \brief Setup EventInput \a index on GenratorClass \a g.
254 * \param g GenratorClass you want to setup.
255 * \param index Number of EventInput you want to setup.
256 * \param name The Name of the Input Connector which will show up in the application.
257 * \param handler When an Event is received on the input this function will be called.
259 * TODO: change the g to a k.
262 PUBLIC void gen_configure_event_input(GeneratorClass *g, gint index,
263 const char *name, AEvent_handler_t handler) {
264 if (g->in_names[index] != NULL)
265 g_warning("Event input already configured: class (%s tag: %s), index %d, name %s, existing name %s",
266 g->name, g->tag, index, name, g->in_names[index]);
268 g->in_names[index] = safe_string_dup(name);
269 g->in_handlers[index] = handler;
273 * \brief Setup EventOutput \a index on GenratorClass \a g.
275 * \param g GenratorClass you want to setup.
276 * \param index Number of EventInput you want to setup.
277 * \param name The Name of the Output Connector which will show up in the application.
280 PUBLIC void gen_configure_event_output(GeneratorClass *g, gint index, const char *name) {
281 if (g->out_names[index] != NULL)
282 g_warning("Event output already configured: class %s, index %d, name %s, existing name %s",
283 g->name, index, name, g->out_names[index]);
285 g->out_names[index] = safe_string_dup(name);
288 PRIVATE GList **make_event_list(gint count) {
289 GList **l = safe_calloc(count, sizeof(GList *));
290 return l;
294 * \brief Instantiate a new Genrator.
296 * \param k The GenratorClass of the Generator.
297 * \param name The name of the new instance.
298 * \return The New Generator.
301 PUBLIC Generator *gen_new_generator(GeneratorClass *k, char *name) {
303 Generator *g = safe_malloc(sizeof(Generator));
304 int i;
306 g->klass = k;
307 g->name = safe_string_dup(name);
309 g->in_events = make_event_list(k->in_count);
310 g->out_events = make_event_list(k->out_count);
311 g->in_signals = make_event_list(k->in_sig_count);
312 g->out_signals = make_event_list(k->out_sig_count);
314 //g->input_events = NULL;
316 g->last_sampletime = safe_calloc( k->out_sig_count, sizeof( SAMPLETIME) );
317 g->last_buffers = safe_calloc(k->out_sig_count, sizeof(SAMPLE *));
318 g->last_buflens = safe_calloc(k->out_sig_count, sizeof(int));
319 g->last_results = safe_calloc(k->out_sig_count, sizeof(gboolean));
320 g->always_cache = safe_calloc(k->out_sig_count, sizeof(gboolean));
322 for( i=0; i<k->out_sig_count; i++ )
323 g->last_buffers[i] = safe_malloc( sizeof(SAMPLE) * MAXIMUM_REALTIME_STEP );
325 g->controls = NULL;
326 g->controls_mutex = g_mutex_new();
328 g->data = NULL;
330 if (k->initialize_instance != NULL &&
331 !k->initialize_instance(g)) {
332 gen_kill_generator(g);
333 return NULL;
336 return g;
339 PRIVATE void empty_link_list(GList *l, int is_signal, int outbound) {
340 while (l != NULL) {
341 GList *next = g_list_next(l);
342 EventLink *el = l->data;
343 GList **rl;
345 if (outbound)
346 rl = &( (is_signal ? el->dst->in_signals : el->dst->in_events) [el->dst_q] );
347 else
348 rl = &( (is_signal ? el->src->out_signals : el->src->out_events) [el->src_q] );
350 *rl = g_list_remove(*rl, el);
352 g_list_free_1(l);
353 l = next;
357 PRIVATE void empty_all_connections(gint count, GList **array, int is_signal, int outbound) {
358 int i;
360 for (i = 0; i < count; i++)
361 empty_link_list(array[i], is_signal, outbound);
365 * \brief Free Memory of Generator \a g
367 * \param g The Genrator to be freed.
369 * Make this function threadsafe:
370 * pass \a g to the audio thread via GAsyncQueue
371 * in audio thread empty_all_connections() and gen_purge_event_queue_ref().
372 * empty_all_connections() uses g_list_free_1() shit i must obtain the malloc lock for this.
374 * BTW: i need to change the g_free() function to use the free_thread i will implement.
376 * then pass on to another thread which does the real destruction of the generator.
378 * looks like i only need to change event_allocation functions. and event_free
379 * normally event is only copied by the generator framework.
382 PUBLIC void gen_kill_generator(Generator *g) {
383 g_async_queue_push( gen_kill_queue, g );
386 PRIVATE void check_for_kills( void ) {
388 Generator *g;
390 while( (g = g_async_queue_try_pop( gen_kill_queue )) != NULL ) {
391 gen_purge_event_queue_refs(g);
392 gen_purge_realtime_fns(g);
394 empty_all_connections(g->klass->in_count, g->in_events, 0, 0);
395 empty_all_connections(g->klass->out_count, g->out_events, 0, 1);
396 empty_all_connections(g->klass->in_sig_count, g->in_signals, 1, 0);
397 empty_all_connections(g->klass->out_sig_count, g->out_signals, 1, 1);
399 //g_print( "Hello a kill \n" );
400 g_async_queue_push( gen_kill_queue_stage2, g );
404 PRIVATE gint gen_kill_generator_stage2_thread() {
406 Generator *g;
407 int i;
408 while( (g = g_async_queue_pop( gen_kill_queue_stage2 )) != (gpointer) -1 )
410 g_mutex_lock( g->controls_mutex );
411 if (g->controls != NULL) {
412 GList *c = g->controls;
413 g->controls = NULL;
415 while (c != NULL) {
416 GList *tmp = g_list_next(c);
418 gdk_threads_enter();
419 control_kill_control(c->data, TRUE);
420 gdk_threads_leave();
421 //g_list_free_1(c);
422 c = tmp;
425 g_mutex_unlock( g->controls_mutex );
426 if (g->klass->destroy_instance != NULL)
427 g->klass->destroy_instance(g);
430 for (i = 0; i < g->klass->out_sig_count; i++)
431 if (g->last_buffers[i] != NULL)
432 safe_free(g->last_buffers[i]);
435 g_mutex_free( g->controls_mutex );
436 safe_free(g->name);
437 safe_free(g->in_events);
438 safe_free(g->out_events);
439 safe_free(g->in_signals);
440 safe_free(g->out_signals);
441 safe_free(g->last_buffers);
442 safe_free(g->last_buflens);
443 safe_free(g->last_results);
444 safe_free(g);
446 return 0;
449 PRIVATE void unpickle_eventlink(ObjectStoreItem *item) {
450 int is_signal = objectstore_item_get_integer(item, "is_signal", FALSE);
451 Generator *src = gen_unpickle(objectstore_item_get_object(item, "src"));
452 int src_q = objectstore_item_get_integer(item, "src_q", 0);
453 Generator *dst = gen_unpickle(objectstore_item_get_object(item, "dst"));
454 int dst_q = objectstore_item_get_integer(item, "dst_q", 0);
456 gen_link(is_signal, src, src_q, dst, dst_q);
459 PRIVATE void unpickle_eventlink_list_array(ObjectStoreDatum *array, ObjectStore *db) {
460 int arraylen = objectstore_datum_array_length(array);
461 int i;
463 for (i = 0; i < arraylen; i++) {
464 ObjectStoreDatum *row = objectstore_datum_array_get(array, i);
465 int rowlen = objectstore_datum_array_length(row);
466 int j;
468 for (j = 0; j < rowlen; j++) {
469 ObjectStoreDatum *elt = objectstore_datum_array_get(row, j);
470 ObjectStoreKey key = objectstore_datum_object_key(elt);
471 ObjectStoreItem *item = objectstore_get_item_by_key(db, key);
472 unpickle_eventlink(item);
478 * \brief unpickles a Generator from the ObjectStoreItem \a item
480 * \param ObjectStoreItem representing the Generator
481 * \return The Generator.
484 PUBLIC Generator *gen_unpickle(ObjectStoreItem *item) {
485 Generator *g = objectstore_get_object(item);
486 GeneratorClass *k;
487 int i;
489 if( item == NULL )
490 return NULL;
492 if (g == NULL) {
493 g = safe_malloc(sizeof(Generator));
494 objectstore_set_object(item, g);
497 char *name = objectstore_item_get_string(item, "class_name", NULL);
498 RETURN_VAL_UNLESS(name != NULL, NULL);
499 k = g_hash_table_lookup(generatorclasses, name);
500 if (k == NULL) {
501 popup_msgbox("Class not found", MSGBOX_CANCEL, 0, MSGBOX_CANCEL,
502 "Generator-class not found: name = %s", name);
503 g_message("Generator Class not found; name = %s", name);
504 //free(g);
505 //return NULL;
507 // Make it the dummy class...
508 // XXX: Saving does not work now.
510 k = g_hash_table_lookup( generatorclasses, "dummy" );
512 g->klass = k;
515 g->name = safe_string_dup(objectstore_item_get_string(item, "name", "anonym"));
516 g->in_events = make_event_list(k->in_count);
517 g->out_events = make_event_list(k->out_count);
518 g->in_signals = make_event_list(k->in_sig_count);
519 g->out_signals = make_event_list(k->out_sig_count);
522 g->last_sampletime = safe_calloc( k->out_sig_count, sizeof( SAMPLETIME) );
523 g->last_buffers = safe_calloc(k->out_sig_count, sizeof(SAMPLE *));
524 g->last_buflens = safe_calloc(k->out_sig_count, sizeof(int));
525 g->last_results = safe_calloc(k->out_sig_count, sizeof(gboolean));
526 g->always_cache = safe_calloc(k->out_sig_count, sizeof(gboolean));
527 for( i=0; i<k->out_sig_count; i++ )
528 g->last_buffers[i] = safe_malloc( sizeof(SAMPLE) * MAXIMUM_REALTIME_STEP );
530 g->controls = NULL;
531 g->controls_mutex = g_mutex_new();
532 g->data = NULL;
534 if (g->klass->unpickle_instance != NULL)
535 g->klass->unpickle_instance(g, item, item->db);
537 unpickle_eventlink_list_array(objectstore_item_get(item, "out_events"), item->db);
538 unpickle_eventlink_list_array(objectstore_item_get(item, "out_signals"), item->db);
539 g->controls = objectstore_extract_list_of_items(objectstore_item_get(item, "controls"),
540 item->db,
541 (objectstore_unpickler_t) control_unpickle);
542 g_list_foreach(g->controls, (GFunc) control_update_value, NULL);
545 return g;
548 PRIVATE ObjectStoreItem *pickle_eventlink(EventLink *el, ObjectStore *db) {
549 ObjectStoreItem *item = objectstore_new_item(db, "EventLink", el);
550 objectstore_item_set_integer(item, "is_signal", el->is_signal);
551 objectstore_item_set_object(item, "src", gen_pickle(el->src, db));
552 objectstore_item_set_integer(item, "src_q", el->src_q);
553 objectstore_item_set_object(item, "dst", gen_pickle(el->dst, db));
554 objectstore_item_set_integer(item, "dst_q", el->dst_q);
555 return item;
558 PRIVATE ObjectStoreDatum *pickle_eventlink_list_array(ObjectStore *db, GList **ar, int n) {
559 ObjectStoreDatum *array = objectstore_datum_new_array(n);
560 int i;
562 for (i = 0; i < n; i++)
563 objectstore_datum_array_set(array, i,
564 objectstore_create_list_of_items(ar[i], db,
565 (objectstore_pickler_t)
566 pickle_eventlink));
568 return array;
572 * \brief Pickle the Generator \a g into ObjectStore \a db.
574 * \param g The Generator to be pickled.
575 * \param db The ObjectStore into which the Generator will be inserted.
579 PUBLIC ObjectStoreItem *gen_pickle(Generator *g, ObjectStore *db) {
580 ObjectStoreItem *item = objectstore_get_item(db, g);
582 if (item == NULL) {
583 item = objectstore_new_item(db, "Generator", g);
584 objectstore_item_set_string(item, "class_name", g->klass->tag);
585 objectstore_item_set_string(item, "name", g->name);
586 objectstore_item_set(item, "out_events",
587 pickle_eventlink_list_array(db, g->out_events, g->klass->out_count));
588 objectstore_item_set(item, "out_signals",
589 pickle_eventlink_list_array(db, g->out_signals, g->klass->out_sig_count));
591 if (g->klass->pickle_instance != NULL)
592 g->klass->pickle_instance(g, item, db);
594 g_mutex_lock( g->controls_mutex );
595 objectstore_item_set(item, "controls",
596 objectstore_create_list_of_items(g->controls, db,
597 (objectstore_pickler_t) control_pickle));
598 g_mutex_unlock( g->controls_mutex );
601 return item;
605 * \brief Pickle the Generator \a g into ObjectStore \a db without EventLink s.
607 * \param g The Generator to be pickled.
608 * \param db The ObjectStore into which the Generator will be inserted.
610 * \return The ObjectStoreItem for this Generator. If it does not exist
611 * It will be created by this function. If it already exists
612 * only the pointer will be returned.
614 * This function pickles a Generator into an ObjectStore, like gen_pickle(),
615 * but it does not pickle the event links.
617 * This is for copy paste. I only modify the core.
618 * The interface, the plugins speak to, is not changed.
619 * i can now write a copy function for a gencomp.
620 * I must still determine the wanted connecttions and pickle them as well.
621 * i will see how this will work....
624 PUBLIC ObjectStoreItem *gen_pickle_without_el(Generator *g, ObjectStore *db) {
625 ObjectStoreItem *item = objectstore_get_item(db, g);
627 if (item == NULL) {
628 item = objectstore_new_item(db, "Generator", g);
629 objectstore_item_set_string(item, "class_name", g->klass->tag);
630 objectstore_item_set_string(item, "name", g->name);
632 objectstore_item_set(item, "out_events",
633 pickle_eventlink_list_array(db, g->out_events, 0));
634 objectstore_item_set(item, "out_signals",
635 pickle_eventlink_list_array(db, g->out_signals, 0));
637 if (g->klass->pickle_instance != NULL)
638 g->klass->pickle_instance(g, item, db);
640 objectstore_item_set(item, "controls", objectstore_datum_new_array(0) );
642 // XXX: Controls should also be copied but they have a reference to
643 // the sheet so i would need a different unpickler.
644 // I wont do that now.
646 //objectstore_item_set(item, "controls",
647 // objectstore_create_list_of_items(g->controls, db,
648 // (objectstore_pickler_t) control_pickle));
651 return item;
656 * \brief Clone the current generator.
658 * \param g The Generator to be cloned.
659 * \param cp ControlPanel where the generator resides.
661 * the generator will be cloned. And its controls will be cloned also.
662 * they will then sit on the the new controlpanel.
665 PUBLIC Generator *gen_clone( Generator *src, ControlPanel *cp ) {
666 ObjectStore *db = objectstore_new_objectstore();
667 ObjectStoreItem *it = gen_pickle_without_el( src, db );
668 Generator *dst;
669 GList *controlX;
671 objectstore_set_object( it, NULL );
672 dst = gen_unpickle( it );
674 objectstore_kill_objectstore( db );
676 g_mutex_lock( src->controls_mutex );
677 for( controlX = src->controls; controlX; controlX = g_list_next( controlX ) ) {
678 Control *c = controlX->data;
679 control_clone( c, dst, cp );
681 g_mutex_unlock( src->controls_mutex );
683 return dst;
687 * \brief Setup a Link between 2 Genrators.
689 * \param is_signal TRUE if a Signal Link is to be established, FALSE for an event Link.
690 * \param src The Source Generator.
691 * \param src_q The Connector number of the Source.
692 * \param dst The Destination Genrator.
693 * \param dst_q The Connector number at the Destination.
695 * \return The EventLink representing this Connection or NULL on failure.
698 PUBLIC EventLink *gen_link(int is_signal, Generator *src, gint32 src_q, Generator *dst, gint32 dst_q) {
699 EventLink *el = gen_find_link(is_signal, src, src_q, dst, dst_q);
701 //g_print( "gen_link_s1_enter() \n" );
702 if (el != NULL)
703 return el;
705 RETURN_VAL_UNLESS(src_q >= 0 && dst_q >= 0, NULL);
707 if (is_signal) {
708 guint32 infl, outfl;
710 if (src_q >= src->klass->out_sig_count || dst_q >= dst->klass->in_sig_count)
711 return NULL;
713 infl = dst->klass->in_sigs[dst_q].flags;
714 outfl = src->klass->out_sigs[src_q].flags;
716 if ((infl & outfl) == 0) {
717 /* No overlap in signaldescriptor capabilities: fail. */
718 return NULL;
720 } else {
721 if (src_q >= src->klass->out_count || dst_q >= dst->klass->in_count)
722 return NULL;
725 el = safe_malloc(sizeof(EventLink));
727 el->is_signal = is_signal;
728 el->src = src;
729 el->src_q = src_q;
730 el->dst = dst;
731 el->dst_q = dst_q;
734 * all setup done now pass this structure to the
735 * realtime thread to actually establish the link.
738 g_async_queue_push( gen_link_queue, el );
740 //g_print( "gen_link_s1_exit() \n" );
741 return el;
744 PRIVATE void check_for_gen_links() {
746 EventLink *el;
747 while( (el = g_async_queue_try_pop( gen_link_queue )) != NULL ) {
749 GList **outq;
750 GList **inq;
752 //g_print( "Enter gen_link_audio \n" );
753 outq = el->is_signal ? el->src->out_signals : el->src->out_events;
754 inq = el->is_signal ? el->dst->in_signals : el->dst->in_events;
756 outq[el->src_q] = g_list_prepend(outq[el->src_q], el);
757 inq[el->dst_q] = g_list_prepend(inq[el->dst_q], el);
759 //g_print( "exit gen_link_audio()\n" );
765 * \brief find a Link between 2 Generators.
767 * \param is_signal TRUE if a Signal Link is to be found, FALSE for an event Link.
768 * \param src The Source Generator.
769 * \param src_q The Connector number of the Source.
770 * \param dst The Destination Genrator.
771 * \param dst_q The Connector number at the Destination.
773 * \return The EventLink representing this Connection.
776 PUBLIC EventLink *gen_find_link(int is_signal,
777 Generator *src, gint32 src_q,
778 Generator *dst, gint32 dst_q) {
779 GList *l;
781 if (src_q >= (is_signal ? src->klass->out_sig_count : src->klass->out_count))
782 return NULL;
784 l = (is_signal ? src->out_signals : src->out_events) [src_q];
786 while (l != NULL) {
787 EventLink *el = l->data;
789 if (el->dst == dst && el->dst_q == dst_q &&
790 el->src == src && el->src_q == src_q &&
791 el->is_signal == is_signal)
792 return el;
794 l = g_list_next(l);
797 return NULL;
801 * \brief Unlink 2 Generators
803 * \param el The EventLink which is to be deleted. Use gen_find_link if you have not saved the EventLink
804 * from the gen_link.
807 PUBLIC void gen_unlink(EventLink *el) {
808 g_async_queue_push( gen_unlink_queue, el );
811 PRIVATE void check_for_gen_unlinks( void ) {
813 EventLink *el;
815 while( (el = g_async_queue_try_pop( gen_unlink_queue )) != NULL ) {
817 GList **outq;
818 GList **inq;
820 g_return_if_fail(el != NULL);
822 outq = (el->is_signal ? el->src->out_signals : el->src->out_events);
823 inq = (el->is_signal ? el->dst->in_signals : el->dst->in_events);
825 outq[el->src_q] = g_list_remove(outq[el->src_q], el);
826 inq[el->dst_q] = g_list_remove(inq[el->dst_q], el);
828 safe_free(el);
833 * \brief Do the checks of the GAsyncQueues for destruction and gen_(un)link
836 PUBLIC void gen_mainloop_do_checks( void ) {
837 check_for_gen_links();
838 check_for_gen_unlinks();
839 check_for_kills();
843 /** \brief Tells the Generator that it has a new Control
845 * \param g The Generator.
846 * \param c The Control.
848 * \note This needs to get thread_safe.
851 PUBLIC void gen_register_control(Generator *g, Control *c) {
852 g_mutex_lock( g->controls_mutex );
853 g->controls = g_list_prepend(g->controls, c);
854 g_mutex_unlock( g->controls_mutex );
857 /** \brief Tells the Generator that a Control is no more.
859 * \param g The Generator.
860 * \param c The Control.
862 * \note This needs to get thread_safe.
865 PUBLIC void gen_deregister_control(Generator *g, Control *c, gboolean lock_taken) {
866 if( !lock_taken )
867 g_mutex_lock( g->controls_mutex );
868 g->controls = g_list_remove(g->controls, c);
869 if( !lock_taken )
870 g_mutex_unlock( g->controls_mutex );
874 * \brief Update all Control `s of the Generator.
876 * This Function calls control_update_value for every Control with the specified Type.
877 * This function should be called when an event is received which changes
878 * Control represented state. For example the value of a gain.
880 * \param g The Genrator which should update.
881 * \param index The number of the Control Type which should update.
882 * or -1 for all Control Types.
884 * \note This function is threadsafe because control_update is.
885 * Well the controls list is not mutexed. FIXME
889 PUBLIC void gen_update_controls(Generator *g, int index) {
890 GList *cs = g->controls;
891 ControlDescriptor *desc = (index == -1) ? NULL : &g->klass->controls[index];
893 if( g_mutex_trylock( g->controls_mutex ) ) {
894 while (cs != NULL) {
895 Control *c = cs->data;
897 if (desc == NULL || c->desc == desc) {
898 control_update_value(c);
900 cs = g_list_next(cs);
903 g_mutex_unlock( g->controls_mutex );
908 * \brief read an input of Type SIG_FLAG_REALTIME into the \buffer.
910 * This function is used to get the realtime signal data.
912 * \param g this Generator.
913 * \param index which input connector
914 * \param attachment_number which of the connected Generator s (should normally be -1 for all)
915 * \param buffer where to put the data.
916 * \param buflen how many samples should be read.
918 * \return TRUE if something was put into the \a buffer.
921 PUBLIC gboolean gen_read_realtime_input(Generator *g, gint index, int attachment_number,
922 SAMPLE *buffer, int buflen) {
923 /* Sanity checks */
924 g_return_val_if_fail(index < g->klass->in_sig_count && index >= 0, FALSE);
925 g_return_val_if_fail((g->klass->in_sigs[index].flags & SIG_FLAG_REALTIME) != 0, FALSE);
927 if (attachment_number == -1 && g_list_next(g->in_signals[index]) == NULL)
928 attachment_number = 0; /* one input? don't bother summing. */
930 if (attachment_number == -1) {
931 SAMPLE tmp[MAXIMUM_REALTIME_STEP];
932 GList *lst = g->in_signals[index];
933 gboolean result = FALSE;
935 memset(buffer, 0, sizeof(SAMPLE) * buflen);
936 while (lst != NULL) {
937 EventLink *el = lst->data;
938 lst = g_list_next(lst);
940 if (gen_read_realtime_output(el->src, el->src_q, tmp, buflen)) {
941 int i;
943 for (i = 0; i < buflen; i++)
944 buffer[i] += tmp[i];
945 result = TRUE;
949 return result;
950 } else {
951 GList *input_list = g_list_nth(g->in_signals[index], attachment_number);
952 EventLink *el;
954 if (input_list == NULL) {
955 memset(buffer, 0, buflen * sizeof(SAMPLE));
956 return FALSE;
959 el = (EventLink *) input_list->data;
960 return gen_read_realtime_output(el->src, el->src_q, buffer, buflen);
965 * \brief read realtime output from a generator and cache it if its necessarry.
967 * I dont think someone would use this function. It is used by gen_read_realtime_input()
968 * to obtain the data from the individual Generator s and cache it if it will be read multiple
969 * times.
971 * \note I must check this for malloc usage on initial call.
973 * \param g the Generator to be read out.
974 * \param index connector number.
975 * \param buffer where the data should be placed.
976 * \param buflen how many SAMPLE s should be read.
978 * \return TRUE if data could be read.
980 * XXX: the event processing will be moved into this function i think.
981 * then we can do local buffer splitting which should improve
982 * performance very much... (i hope at least)
984 * now to the other stuff :)
985 * how about those pure event processors ?
986 * shall we really switch to the XAP process() semantics ?
988 * events could very well be processed through the chains until they
989 * get stuck on a realtime component.
991 * and the plugins can still get their realtime callbacks for event
992 * emission.
994 * hmm... lets see where this will take us...
996 * how about queuing some events locally and queueing the others
997 * globally ?
999 * if plugin has realtime ins or outs it can process events from
1000 * local queue. if not use the global queue for now....
1002 * cool... nice migration path... make it so.
1008 PUBLIC gboolean gen_read_realtime_output(Generator *g, gint index, SAMPLE *buffer, int buflen) {
1009 /* Sanity checks */
1010 g_return_val_if_fail(index < g->klass->out_sig_count && index >= 0, FALSE);
1011 g_return_val_if_fail((g->klass->out_sigs[index].flags & SIG_FLAG_REALTIME) != 0, FALSE);
1013 if (g_list_next(g->out_signals[index]) == NULL) {
1014 /* Don't bother caching the only output. */
1015 if( g->last_sampletime[index] == gen_get_sampletime() ) {
1016 // this looks like a loop.
1017 // we must do something to break the cycle.
1018 // XXX:
1019 g->always_cache[index] = TRUE;
1020 return FALSE;
1021 // something smarter would be cool.
1022 // we basically need to cache our output now.
1023 // so we need to mark it for caching.
1025 return g->klass->out_sigs[index].d.realtime(g, buffer, buflen);
1026 } else {
1027 /* Cache for multiple outputs... you never know who'll be reading you, or how often */
1028 if (g->last_buffers[index] == NULL || g->last_sampletime[index] < gen_get_sampletime()) {
1030 /* Cache is not present, or expired */
1033 * why is this freed and malloced all the time ?
1034 * should be malloced only if buflen > act_buflen
1035 * or last_buflen if that has no side effects.
1038 //if (g->last_buffers[index] != NULL)
1039 //free(g->last_buffers[index]);
1040 //g->last_buffers[index] = malloc(sizeof(SAMPLE) * buflen);
1041 //------------------------------------------------------------------
1043 g->last_buflens[index] = buflen;
1044 g->last_sampletime[index] = gen_get_sampletime();
1045 g->last_results[index] =
1046 g->klass->out_sigs[index].d.realtime(g, g->last_buffers[index], buflen);
1047 } else if (g->last_buflens[index] < buflen) {
1048 /* A small chunk was read. Fill it out. */
1049 //SAMPLE *newbuf = malloc(sizeof(SAMPLE) * buflen);
1050 int oldlen = g->last_buflens[index];
1053 * ooh... this is not necessarry at all.
1054 * have one buffer sized MAX_REALTIME_STEP and all should be fine.
1055 * handling of last_buflen must remaim.
1056 * the buffers need to be allocated in gen_new_generator() and gen_unpickle()
1059 //if (g->last_results[index])
1060 //memcpy(newbuf, g->last_buffers[index], sizeof(SAMPLE) * g->last_buflens[index]);
1061 //else
1062 //memset(newbuf, 0, sizeof(SAMPLE) * g->last_buflens[index]);
1063 //free(g->last_buffers[index]);
1064 //g->last_buffers[index] = newbuf;
1065 g->last_buflens[index] = buflen;
1066 g->last_results[index] =
1067 g->klass->out_sigs[index].d.realtime(g, &g->last_buffers[index][oldlen], buflen - oldlen);
1070 if (g->last_results[index])
1071 memcpy(buffer, g->last_buffers[index], buflen * sizeof(SAMPLE));
1072 return g->last_results[index];
1077 * \brief Read output range for this Generator.
1079 * This function should not be used by the user.
1080 * it is called by gen_get_randomaccess_input_range().
1082 * \param g Generator to read out.
1083 * \param index number of output connector.
1085 * \return the number of samples the randonacces provides.
1088 PUBLIC SAMPLETIME gen_get_randomaccess_output_range(Generator *g, gint index) {
1089 SAMPLETIME (*fn)(Generator *, OutputSignalDescriptor *);
1091 /* Sanity checks */
1092 g_return_val_if_fail(index < g->klass->out_sig_count || index >= 0, 0);
1093 g_return_val_if_fail((g->klass->out_sigs[index].flags & SIG_FLAG_RANDOMACCESS) != 0, 0);
1095 fn = g->klass->out_sigs[index].d.randomaccess.get_range;
1097 if (fn)
1098 return fn(g, &g->klass->out_sigs[index]);
1099 else {
1100 g_warning("Generator (%s tag: %s) does not implement get_range", g->klass->name, g->klass->tag);
1101 return 0;
1106 * \brief Get the randomaccess input range
1108 * \param g This Generator
1109 * \param index Which input connector
1110 * \param attachment_number which connection or -1 for all connections
1112 * \return the length of the given RandomAccess Input.
1115 PUBLIC SAMPLETIME gen_get_randomaccess_input_range(Generator *g, gint index,
1116 int attachment_number) {
1117 GList *input_list;
1118 EventLink *el;
1119 OutputSignalDescriptor *desc;
1121 /* Sanity checks */
1122 g_return_val_if_fail(index < g->klass->in_sig_count && index >= 0, FALSE);
1123 g_return_val_if_fail((g->klass->in_sigs[index].flags & SIG_FLAG_RANDOMACCESS) != 0, FALSE);
1124 g_return_val_if_fail(attachment_number != -1, FALSE);
1126 input_list = g_list_nth(g->in_signals[index], attachment_number);
1127 if (input_list == NULL) {
1128 /*memset(buffer, 0, buflen * sizeof(SAMPLE));*/
1129 return 0;
1132 el = (EventLink *) input_list->data;
1133 desc = &el->src->klass->out_sigs[el->src_q];
1134 return desc->d.randomaccess.get_range(el->src, desc);
1138 * \brief Get the randomaccess input
1140 * \param g This Generator
1141 * \param index Which input connector
1142 * \param attachment_number which connection or -1 for all connections
1143 * \param offset Get input from which offset.
1144 * \param buflen How many SAMPLE s.
1146 * \retval buffer Where to put the data.
1147 * \return TRUE if the data has been put into the buffer.
1150 PUBLIC gboolean gen_read_randomaccess_input(Generator *g, gint index, int attachment_number,
1151 SAMPLETIME offset, SAMPLE *buffer, int buflen) {
1152 GList *input_list;
1153 EventLink *el;
1154 OutputSignalDescriptor *desc;
1156 /* Sanity checks */
1157 g_return_val_if_fail(index < g->klass->in_sig_count && index >= 0, FALSE);
1158 g_return_val_if_fail((g->klass->in_sigs[index].flags & SIG_FLAG_RANDOMACCESS) != 0, FALSE);
1159 g_return_val_if_fail(attachment_number != -1, FALSE);
1161 input_list = g_list_nth(g->in_signals[index], attachment_number);
1162 if (input_list == NULL) {
1163 /*memset(buffer, 0, buflen * sizeof(SAMPLE));*/
1164 return FALSE;
1167 el = (EventLink *) input_list->data;
1168 desc = &el->src->klass->out_sigs[el->src_q];
1169 return desc->d.randomaccess.get_samples(el->src, desc, offset, buffer, buflen);
1174 * \brief render gl inputs
1176 * \param g This Generator
1177 * \param index Which input connector
1178 * \param attachment_number which connection or -1 for all connections
1180 * \return TRUE if something was rendered.
1182 * This function calls the render gl method of the connected generators.
1183 * See the renderfunction of gltranslate.
1185 * \code
1186 * PRIVATE gboolean render_function(Generator *g ) {
1188 * Data *data = g->data;
1190 * glPushMatrix();
1191 * glTranslatef( data->tx, data->ty, data->tz );
1192 * gen_render_gl( g, 0, -1 );
1193 * glPopMatrix();
1195 * return TRUE;
1198 * \endcode
1201 PUBLIC gboolean gen_render_gl(Generator *g, gint index, int attachment_number ) {
1203 GList *input_list;
1204 EventLink *el;
1205 OutputSignalDescriptor *desc;
1207 /* Sanity checks */
1208 g_return_val_if_fail(index < g->klass->in_sig_count && index >= 0, FALSE);
1209 g_return_val_if_fail((g->klass->in_sigs[index].flags & SIG_FLAG_OPENGL) != 0, FALSE);
1211 if (g->in_signals[index] == NULL) {
1212 /*memset(buffer, 0, buflen * sizeof(SAMPLE));*/
1213 return FALSE;
1216 for( input_list = g->in_signals[index]; input_list != NULL; input_list = g_list_next( input_list ) ) {
1218 el = (EventLink *) input_list->data;
1219 desc = &el->src->klass->out_sigs[el->src_q];
1220 desc->d.render_gl(el->src);
1222 return TRUE;
1225 PRIVATE void send_one_event(EventLink *el, AEvent *e) {
1226 e->dst = el->dst;
1227 e->dst_q = el->dst_q;
1228 gen_post_aevent(e);
1232 * \brief send an event to an output connector
1234 * \param g The Generator we are sending from
1235 * \param index The number of the Connector we send the event from.
1236 * \param attachment_number number of eventlink to send the event to. (-1 for all)
1237 * \param e Pointer to event we want to send. This is copied and can be freed after the call.
1239 * It is general practise to use a received event as \a e here. See the event processing function of
1240 * plugins/evtadd.c
1242 * \code
1243 * PRIVATE void evt_input_handler(Generator *g, AEvent *event) {
1245 * Data *data = g->data;
1247 * event->d.number += data->addend;
1248 * gen_send_events(g, EVT_OUTPUT, -1, event);
1250 * \endcode
1252 * With this method we dont have to bother with the timestamp of the event.
1253 * But after being passed to the evt_input_handler() the AEvent is freed
1254 * by gen_mainloop_once(). if you changed the type of the event to AE_STRING
1255 * or AE_NUMARRAY the memory at event->d.string or event->d.array.number
1256 * would be freed also. If this memory is already freed galan will segfault.
1258 * So be careful. Set event->kind back to AE_NUMBER if you received an AE_NUMBER AEvent.
1259 * I see no way to prevent you from making this error except forbidding this practise.
1260 * But its efficient so i dont forbid this.
1263 PUBLIC void gen_send_events(Generator *g, gint index, int attachment_number, AEvent *e) {
1264 e->src = g;
1265 e->src_q = index;
1267 if (attachment_number == -1)
1268 g_list_foreach(g->out_events[index], (GFunc) send_one_event, e);
1269 else {
1270 GList *output = g_list_nth(g->out_events[index], attachment_number);
1272 if (output != NULL) {
1273 EventLink *el = output->data;
1274 e->dst = el->dst;
1275 e->dst_q = el->dst_q;
1276 gen_post_aevent(e);
1282 // Dummy Generator...
1284 PRIVATE gboolean init_dummy(Generator *g) {
1285 return TRUE;
1288 PRIVATE void done_dummy(Generator *g) {
1291 PRIVATE gboolean dummy_output_generator(Generator *g, SAMPLE *buf, int buflen) {
1293 return FALSE;
1296 PRIVATE void evt_dummy_handler(Generator *g, AEvent *event) {
1299 PRIVATE InputSignalDescriptor input_sigs[] = {
1300 { "Input1", SIG_FLAG_REALTIME },
1301 { "Input2", SIG_FLAG_REALTIME },
1302 { "Input3", SIG_FLAG_REALTIME },
1303 { "Input4", SIG_FLAG_REALTIME },
1304 { "Input5", SIG_FLAG_REALTIME },
1305 { "Input6", SIG_FLAG_REALTIME },
1306 { "Input7", SIG_FLAG_REALTIME },
1307 { "Input8", SIG_FLAG_REALTIME },
1308 { "Input9", SIG_FLAG_REALTIME },
1309 { "Input10", SIG_FLAG_REALTIME },
1310 { "Input11", SIG_FLAG_REALTIME },
1311 { "Input12", SIG_FLAG_REALTIME },
1312 { NULL, }
1316 PRIVATE OutputSignalDescriptor output_sigs[] = {
1317 { "Output1", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1318 { "Output2", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1319 { "Output3", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1320 { "Output4", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1321 { "Output5", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1322 { "Output6", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1323 { "Output7", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1324 { "Output8", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1325 { "Output9", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1326 { "Output10", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1327 { "Output11", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1328 { "Output12", SIG_FLAG_REALTIME, { dummy_output_generator, } },
1329 { NULL, }
1332 PRIVATE ControlDescriptor dummy_controls[] = {
1333 /* { kind, name, min,max,step,page, size,editable, is_dst,queue_number,
1334 init,destroy,refresh,refresh_data }, */
1335 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1336 NULL,NULL, NULL, NULL },
1337 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1338 NULL,NULL, NULL, NULL },
1339 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1340 NULL,NULL, NULL, NULL },
1341 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1342 NULL,NULL, NULL, NULL },
1343 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1344 NULL,NULL, NULL, NULL },
1345 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1346 NULL,NULL, NULL, NULL },
1347 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1348 NULL,NULL, NULL, NULL },
1349 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1350 NULL,NULL, NULL, NULL },
1351 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1352 NULL,NULL, NULL, NULL },
1353 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1354 NULL,NULL, NULL, NULL },
1355 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1356 NULL,NULL, NULL, NULL },
1357 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1358 NULL,NULL, NULL, NULL },
1359 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1360 NULL,NULL, NULL, NULL },
1361 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1362 NULL,NULL, NULL, NULL },
1363 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1364 NULL,NULL, NULL, NULL },
1365 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1366 NULL,NULL, NULL, NULL },
1367 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1368 NULL,NULL, NULL, NULL },
1369 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1370 NULL,NULL, NULL, NULL },
1371 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1372 NULL,NULL, NULL, NULL },
1373 { CONTROL_KIND_KNOB, "defect", 0,5,0.01,0.01, 0,TRUE, TRUE,0,
1374 NULL,NULL, NULL, NULL },
1375 { CONTROL_KIND_NONE, }
1377 PRIVATE void init_dummy_generator( void ) {
1379 int i;
1380 GeneratorClass *k = gen_new_generatorclass("dummy", FALSE,
1381 120, 120,
1382 input_sigs, output_sigs, dummy_controls,
1383 init_dummy, done_dummy,
1384 (AGenerator_pickle_t) init_dummy, NULL);
1387 for( i=0; i<120; i++ ) {
1388 gen_configure_event_output( k, i, "Out" );
1389 gen_configure_event_input( k, i, "In", evt_dummy_handler );
1393 PUBLIC GHashTable *get_generator_classes( void ) {
1394 return generatorclasses;
1397 PUBLIC void init_generator_thread(void) {
1399 GError *err;
1400 kill_thread = g_thread_create( (GThreadFunc) gen_kill_generator_stage2_thread, NULL, TRUE, &err );
1403 PUBLIC void init_generator(void) {
1405 gen_samplerate = jack_get_sample_rate( galan_jack_get_client() );
1407 gen_link_queue = g_async_queue_new();
1408 gen_unlink_queue = g_async_queue_new();
1409 gen_kill_queue = g_async_queue_new();
1410 gen_kill_queue_stage2 = g_async_queue_new();
1413 generatorclasses = g_hash_table_new(g_str_hash, g_str_equal);
1415 init_dummy_generator();
1418 PUBLIC void done_generator(void) {
1420 g_async_queue_push( gen_kill_queue_stage2, (gpointer) -1 );
1421 g_thread_join( kill_thread );
1423 g_hash_table_destroy(generatorclasses);
1424 generatorclasses = NULL;
1426 g_async_queue_unref( gen_link_queue );
1427 g_async_queue_unref( gen_unlink_queue );
1428 g_async_queue_unref( gen_kill_queue );
1429 g_async_queue_unref( gen_kill_queue_stage2 );