1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public License
7  * as published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20 
21 
22 #ifndef _FLUID_RVOICE_EVENT_H
23 #define _FLUID_RVOICE_EVENT_H
24 
25 #include "fluidsynth_priv.h"
26 #include "fluid_rvoice_mixer.h"
27 #include "fluid_ringbuffer.h"
28 
29 #define EVENT_REAL_PARAMS (5)
30 
31 typedef struct _fluid_rvoice_event_t fluid_rvoice_event_t;
32 typedef struct _fluid_rvoice_eventhandler_t fluid_rvoice_eventhandler_t;
33 
34 struct _fluid_rvoice_event_t {
35 	void* method;
36 	void* object;
37 	void* ptr;
38 	int intparam;
39 	fluid_real_t realparams[EVENT_REAL_PARAMS];
40 };
41 
42 void fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event);
43 
44 
45 /**
46  * Bridge between the renderer thread and the midi state thread.
47  * If is_threadsafe is true, that means fluid_rvoice_eventhandler_fetch_all
48  * can be called in parallell with fluid_rvoice_eventhandler_push/flush
49  */
50 struct _fluid_rvoice_eventhandler_t {
51 	int is_threadsafe; /* False for optimal performance, true for atomic operations */
52 	fluid_ringbuffer_t* queue; /**< List of fluid_rvoice_event_t */
53         int queue_stored; /**< Extras pushed but not flushed */
54 	fluid_ringbuffer_t* finished_voices; /**< return queue from handler, list of fluid_rvoice_t* */
55 	fluid_rvoice_mixer_t* mixer;
56 };
57 
58 fluid_rvoice_eventhandler_t* new_fluid_rvoice_eventhandler(
59   int is_threadsafe, int queuesize, int finished_voices_size, int bufs,
60   int fx_bufs, fluid_real_t sample_rate);
61 
62 void delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t*);
63 
64 int fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t*);
65 int fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t*);
66 
67 static FLUID_INLINE void
fluid_rvoice_eventhandler_flush(fluid_rvoice_eventhandler_t * handler)68 fluid_rvoice_eventhandler_flush(fluid_rvoice_eventhandler_t* handler)
69 {
70   if (handler->queue_stored > 0) {
71     fluid_ringbuffer_next_inptr(handler->queue, handler->queue_stored);
72     handler->queue_stored = 0;
73   }
74 }
75 
76 /**
77  * @return next finished voice, or NULL if nothing in queue
78  */
79 static FLUID_INLINE fluid_rvoice_t*
fluid_rvoice_eventhandler_get_finished_voice(fluid_rvoice_eventhandler_t * handler)80 fluid_rvoice_eventhandler_get_finished_voice(fluid_rvoice_eventhandler_t* handler)
81 {
82   void* result = fluid_ringbuffer_get_outptr(handler->finished_voices);
83   if (result == NULL) return NULL;
84   result = * (fluid_rvoice_t**) result;
85   fluid_ringbuffer_next_outptr(handler->finished_voices);
86   return result;
87 }
88 
89 
90 int fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler,
91                                 void* method, void* object, int intparam,
92                                 fluid_real_t realparam);
93 
94 int fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler,
95                                 void* method, void* object, void* ptr);
96 
97 int fluid_rvoice_eventhandler_push5(fluid_rvoice_eventhandler_t* handler,
98                                 void* method, void* object, int intparam,
99                                 fluid_real_t r1, fluid_real_t r2,
100                                 fluid_real_t r3, fluid_real_t r4, fluid_real_t r5);
101 
102 static FLUID_INLINE void
fluid_rvoice_eventhandler_add_rvoice(fluid_rvoice_eventhandler_t * handler,fluid_rvoice_t * rvoice)103 fluid_rvoice_eventhandler_add_rvoice(fluid_rvoice_eventhandler_t* handler,
104                                      fluid_rvoice_t* rvoice)
105 {
106   if (handler->is_threadsafe)
107     fluid_rvoice_eventhandler_push_ptr(handler, fluid_rvoice_mixer_add_voice,
108                                        handler->mixer, rvoice);
109   else
110     fluid_rvoice_mixer_add_voice(handler->mixer, rvoice);
111 }
112 
113 
114 
115 #endif
116