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
27 #include "generator.h"
31 #include "galan_jack.h"
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
;
42 * \brief This queue contains EventLinks which should be added to the system.
45 PRIVATE GAsyncQueue
*gen_link_queue
;
47 * \brief This queue contains EventLinks which should be removed from the system.
50 PRIVATE GAsyncQueue
*gen_unlink_queue
;
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
;
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
);
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
) {
124 gen_new_generatorclass_with_different_tag( name
, name
, prefer
,
125 count_event_in
, count_event_out
,
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
)
177 for (k
->in_sig_count
= 0;
178 k
->in_sigs
[k
->in_sig_count
].name
!= NULL
;
181 if (output_sigs
== NULL
)
182 k
->out_sig_count
= 0;
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
)
191 for (k
->numcontrols
= 0;
192 k
->controls
[k
->numcontrols
].kind
!= CONTROL_KIND_NONE
;
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
);
212 g_hash_table_insert(generatorclasses
, k
->tag
, k
);
214 g_hash_table_remove(generatorclasses
, k
->tag
);
215 g_hash_table_insert(generatorclasses
, k
->tag
, 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
228 * \param g GenratorClass to free.
231 PUBLIC
void gen_kill_generatorclass(GeneratorClass
*g
) {
237 for (i
= 0; i
< g
->in_count
; i
++)
238 if (g
->in_names
[i
] != NULL
)
239 free(g
->in_names
[i
]);
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
]);
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
*));
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
));
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
);
326 g
->controls_mutex
= g_mutex_new();
330 if (k
->initialize_instance
!= NULL
&&
331 !k
->initialize_instance(g
)) {
332 gen_kill_generator(g
);
339 PRIVATE
void empty_link_list(GList
*l
, int is_signal
, int outbound
) {
341 GList
*next
= g_list_next(l
);
342 EventLink
*el
= l
->data
;
346 rl
= &( (is_signal
? el
->dst
->in_signals
: el
->dst
->in_events
) [el
->dst_q
] );
348 rl
= &( (is_signal
? el
->src
->out_signals
: el
->src
->out_events
) [el
->src_q
] );
350 *rl
= g_list_remove(*rl
, el
);
357 PRIVATE
void empty_all_connections(gint count
, GList
**array
, int is_signal
, int outbound
) {
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 ) {
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() {
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
;
416 GList
*tmp
= g_list_next(c
);
419 control_kill_control(c
->data
, TRUE
);
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
);
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
);
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
);
463 for (i
= 0; i
< arraylen
; i
++) {
464 ObjectStoreDatum
*row
= objectstore_datum_array_get(array
, i
);
465 int rowlen
= objectstore_datum_array_length(row
);
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
);
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
);
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
);
507 // Make it the dummy class...
508 // XXX: Saving does not work now.
510 k
= g_hash_table_lookup( generatorclasses
, "dummy" );
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
);
531 g
->controls_mutex
= g_mutex_new();
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"),
541 (objectstore_unpickler_t
) control_unpickle
);
542 g_list_foreach(g
->controls
, (GFunc
) control_update_value
, NULL
);
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
);
558 PRIVATE ObjectStoreDatum
*pickle_eventlink_list_array(ObjectStore
*db
, GList
**ar
, int n
) {
559 ObjectStoreDatum
*array
= objectstore_datum_new_array(n
);
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
)
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
);
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
);
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
);
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));
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
);
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
);
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" );
705 RETURN_VAL_UNLESS(src_q
>= 0 && dst_q
>= 0, NULL
);
710 if (src_q
>= src
->klass
->out_sig_count
|| dst_q
>= dst
->klass
->in_sig_count
)
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. */
721 if (src_q
>= src
->klass
->out_count
|| dst_q
>= dst
->klass
->in_count
)
725 el
= safe_malloc(sizeof(EventLink
));
727 el
->is_signal
= is_signal
;
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" );
744 PRIVATE
void check_for_gen_links() {
747 while( (el
= g_async_queue_try_pop( gen_link_queue
)) != NULL
) {
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
) {
781 if (src_q
>= (is_signal
? src
->klass
->out_sig_count
: src
->klass
->out_count
))
784 l
= (is_signal
? src
->out_signals
: src
->out_events
) [src_q
];
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
)
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
807 PUBLIC
void gen_unlink(EventLink
*el
) {
808 g_async_queue_push( gen_unlink_queue
, el
);
811 PRIVATE
void check_for_gen_unlinks( void ) {
815 while( (el
= g_async_queue_try_pop( gen_unlink_queue
)) != NULL
) {
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
);
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();
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
) {
867 g_mutex_lock( g
->controls_mutex
);
868 g
->controls
= g_list_remove(g
->controls
, c
);
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
) ) {
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
) {
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
)) {
943 for (i
= 0; i
< buflen
; i
++)
951 GList
*input_list
= g_list_nth(g
->in_signals
[index
], attachment_number
);
954 if (input_list
== NULL
) {
955 memset(buffer
, 0, buflen
* sizeof(SAMPLE
));
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
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
994 * hmm... lets see where this will take us...
996 * how about queuing some events locally and queueing the others
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
) {
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.
1019 g
->always_cache
[index
] = TRUE
;
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
);
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]);
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
*);
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
;
1098 return fn(g
, &g
->klass
->out_sigs
[index
]);
1100 g_warning("Generator (%s tag: %s) does not implement get_range", g
->klass
->name
, g
->klass
->tag
);
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
) {
1119 OutputSignalDescriptor
*desc
;
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));*/
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
) {
1154 OutputSignalDescriptor
*desc
;
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));*/
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.
1186 * PRIVATE gboolean render_function(Generator *g ) {
1188 * Data *data = g->data;
1191 * glTranslatef( data->tx, data->ty, data->tz );
1192 * gen_render_gl( g, 0, -1 );
1201 PUBLIC gboolean
gen_render_gl(Generator
*g
, gint index
, int attachment_number
) {
1205 OutputSignalDescriptor
*desc
;
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));*/
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
);
1225 PRIVATE
void send_one_event(EventLink
*el
, AEvent
*e
) {
1227 e
->dst_q
= el
->dst_q
;
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
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);
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
) {
1267 if (attachment_number
== -1)
1268 g_list_foreach(g
->out_events
[index
], (GFunc
) send_one_event
, e
);
1270 GList
*output
= g_list_nth(g
->out_events
[index
], attachment_number
);
1272 if (output
!= NULL
) {
1273 EventLink
*el
= output
->data
;
1275 e
->dst_q
= el
->dst_q
;
1282 // Dummy Generator...
1284 PRIVATE gboolean
init_dummy(Generator
*g
) {
1288 PRIVATE
void done_dummy(Generator
*g
) {
1291 PRIVATE gboolean
dummy_output_generator(Generator
*g
, SAMPLE
*buf
, int buflen
) {
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
},
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
, } },
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 ) {
1380 GeneratorClass
*k
= gen_new_generatorclass("dummy", FALSE
,
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) {
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
);