6 qn_pattern_t
* loop_one(void* ctx
) {
7 qn_context_t
* real_ctx
= ctx
;
8 return real_ctx
->run
->curr
;
11 static qn_pattern_t
* advance_pattern(void* ctx
, int loop
) {
12 qn_context_t
* real_ctx
= ctx
;
13 qn_config_t
* config
= real_ctx
->config
;
15 for(i
=0; i
<config
->npatterns
; i
++) {
16 qn_pattern_t
* pat
= config
->patterns
+ i
;
17 if(pat
== real_ctx
->run
->curr
) {
19 if(patindex
==config
->npatterns
) {
26 return config
->patterns
+ patindex
;
31 qn_pattern_t
* loop_all(void* ctx
) {
32 return advance_pattern(ctx
,1);
34 qn_pattern_t
* once_through(void* ctx
) {
35 return advance_pattern(ctx
,0);
38 qn_config_t
* qn_get_fake_config() {
39 qn_config_t
* config
= malloc(sizeof(qn_config_t
));
40 qn_init_config(config
);
42 config
->noutports
= 1;
43 char* portname
= "fluidsynth";
44 config
->outports
= malloc(sizeof(qn_config_port_t
) * config
->noutports
);
45 config
->outports
[0].name
= strndup(portname
,strlen(portname
));
46 config
->outports
[0].clock_numerator
= 0;
47 config
->outports
[0].clock_denominator
= 0;
50 config
->voices
= malloc(sizeof(qn_voice_t
) * config
->nvoices
);
51 char* voicename
= "bass";
52 config
->voices
[0].name
= strndup(voicename
,strlen(voicename
));
54 for(i
=0; i
<config
->noutports
; i
++) {
55 /* fprintf(stderr,"First, does %s equal %s\n","fluidsynth",config->outports[i]); */
56 if(!strcmp("fluidsynth",config
->outports
[i
].name
)) {
57 config
->voices
[0].portname
= config
->outports
[i
].name
;
61 config
->voices
[0].channel
= 14;
62 config
->voices
[0].port
= NULL
;
64 config
->npatterns
= 2;
65 config
->patterns
= malloc(sizeof(qn_pattern_t
) * config
->npatterns
);
69 p
->npatternvoices
= 2;
70 p
->patternvoices
= malloc(sizeof(qn_patternvoice_t
) * p
->npatternvoices
);
71 p
->beats_per_minute
= 144;
72 p
->bpm_relation
= Absolute
;
73 p
->tbm_ticks_per_beat
= 2;
74 p
->tbm_beats_per_bar
= 4;
77 qn_patternvoice_t
* pv
= p
->patternvoices
+ 0;
78 pv
->voice
= config
->voices
+ 0;
81 pv
->events
= malloc(sizeof(qn_event_t
) * pv
->nevents
);
82 pv
->events
[0].start_tick
= 0;
83 pv
->events
[0].data
[0] = 0x90; // note on
84 pv
->events
[0].data
[1] = 60; // pitch
85 pv
->events
[0].data
[2] = 110; // vel
86 pv
->events
[1].start_tick
= 6;
87 pv
->events
[1].data
[0] = 0x80; // note off
88 pv
->events
[1].data
[1] = 60; // pitch
90 pv
= p
->patternvoices
+ 1;
91 pv
->voice
= config
->voices
+ 0;
94 pv
->events
= malloc(sizeof(qn_event_t
) * pv
->nevents
);
95 pv
->events
[0].start_tick
= 0;
96 pv
->events
[0].data
[0] = 0x90; // note on
97 pv
->events
[0].data
[1] = 53; // pitch
98 pv
->events
[0].data
[2] = 64; // vel
99 pv
->events
[1].start_tick
= 1;
100 pv
->events
[1].data
[0] = 0x80; // note off
101 pv
->events
[1].data
[1] = 53; // pitch
105 p
= config
->patterns
+ 1;
106 p
->npatternvoices
= 1;
107 p
->patternvoices
= malloc(sizeof(qn_patternvoice_t
) * p
->npatternvoices
);
108 p
->beats_per_minute
= 56;
109 p
->tbm_ticks_per_beat
= 2;
110 p
->tbm_beats_per_bar
= 4;
111 p
->tbm_beat_type
= 4;
112 p
->bpm_relation
= RelativeToBase
;
114 pv
= p
->patternvoices
+ 0;
115 pv
->voice
= config
->voices
+ 0;
118 pv
->events
= malloc(sizeof(qn_event_t
) * pv
->nevents
);
119 pv
->events
[0].start_tick
= 0;
120 pv
->events
[0].data
[0] = 0x90; // note on
121 pv
->events
[0].data
[1] = 58; // pitch
122 pv
->events
[0].data
[2] = 64; // vel
123 pv
->events
[1].start_tick
= 1;
124 pv
->events
[1].data
[0] = 0x80; // note off
125 pv
->events
[1].data
[1] = 58; // pitch
127 pv
->events
[2].start_tick
= 0;
128 pv
->events
[2].data
[0] = 0x90; // note on
129 pv
->events
[2].data
[1] = 67; // pitch
130 pv
->events
[2].data
[2] = 64; // vel
131 pv
->events
[3].start_tick
= 2;
132 pv
->events
[3].data
[0] = 0x80; // note off
133 pv
->events
[3].data
[1] = 67; // pitch
135 pv
->events
[4].start_tick
= 2;
136 pv
->events
[4].data
[0] = 0x90; // note on
137 pv
->events
[4].data
[1] = 58; // pitch
138 pv
->events
[4].data
[2] = 64; // vel
139 pv
->events
[5].start_tick
= 3;
140 pv
->events
[5].data
[0] = 0x80; // note off
141 pv
->events
[5].data
[1] = 58; // pitch
144 pv
->events
[6].start_tick
= 4;
145 pv
->events
[6].data
[0] = 0x90; // note on
146 pv
->events
[6].data
[1] = 59; // pitch
147 pv
->events
[6].data
[2] = 64; // vel
148 pv
->events
[7].start_tick
= 5;
149 pv
->events
[7].data
[0] = 0x80; // note off
150 pv
->events
[7].data
[1] = 59; // pitch
152 pv
->events
[8].start_tick
= 4;
153 pv
->events
[8].data
[0] = 0x90; // note on
154 pv
->events
[8].data
[1] = 67; // pitch
155 pv
->events
[8].data
[2] = 64; // vel
156 pv
->events
[9].start_tick
= 6;
157 pv
->events
[9].data
[0] = 0x80; // note off
158 pv
->events
[9].data
[1] = 67; // pitch
160 pv
->events
[10].start_tick
= 6;
161 pv
->events
[10].data
[0] = 0x90; // note on
162 pv
->events
[10].data
[1] = 59; // pitch
163 pv
->events
[10].data
[2] = 64; // vel
164 pv
->events
[11].start_tick
= 7;
165 pv
->events
[11].data
[0] = 0x80; // note off
166 pv
->events
[11].data
[1] = 59; // pitch
168 config
->next_pattern_func
= loop_all
;
173 void qn_init_config(qn_config_t
* config
) {
175 config
->voices
= NULL
;
176 config
->noutports
= 0;
177 config
->outports
= NULL
;
178 config
->npatterns
= 0;
179 config
->patterns
= NULL
;
180 config
->next_pattern_func
= NULL
;
183 qn_context_t
* qn_init_context(qn_config_t
* config
, jack_client_t
* client
) {
184 qn_context_t
* ctx
= malloc(sizeof(qn_context_t
));
185 ctx
->config
= config
;
187 ctx
->run
= malloc(sizeof(qn_runstate_t
));
188 ctx
->run
->client
= client
;
189 ctx
->run
->ports
= malloc(sizeof(qn_port_t
*) * config
->noutports
);
190 ctx
->run
->awaiting_common_start_beat
= 0;
192 for(i
=0; i
<config
->noutports
; i
++) {
193 ctx
->run
->ports
[i
] = malloc(sizeof(qn_port_t
));
194 ctx
->run
->ports
[i
]->jackport
=
195 jack_port_register(client
, config
->outports
[i
].name
,
196 JACK_DEFAULT_MIDI_TYPE
, JackPortIsOutput
, 0);
197 ctx
->run
->ports
[i
]->clock_numerator
= config
->outports
[i
].clock_numerator
;
198 /* printf("Set num to %d\n",ctx->run->ports[i]->clock_numerator); */
199 ctx
->run
->ports
[i
]->clock_denominator
= config
->outports
[i
].clock_denominator
;
200 ctx
->run
->ports
[i
]->clock_next_tick
= 0;
201 ctx
->run
->ports
[i
]->clock_tick_index
= 0;
204 // Set the port on each voice
205 for(i
=0; i
<config
->nvoices
; i
++) {
208 for(j
=0; j
<config
->noutports
; j
++) {
209 /* fprintf(stderr,"Does %s equal %s\n",config->outports[j],config->voices[i].portname); */
210 if(!strcmp(config
->outports
[j
].name
,config
->voices
[i
].portname
)) {
211 config
->voices
[i
].port
= ctx
->run
->ports
[j
];
217 fprintf(stderr
,"No port was created for this voice\n");
221 // Identify the longest patternvoice for each pattern
222 for(i
=0; i
<config
->npatterns
; i
++) {
223 qn_pattern_t
* pat
= config
->patterns
+ i
;
224 int j
, max_beats
= 0;
225 for(j
=0; j
<pat
->npatternvoices
; j
++) {
226 qn_patternvoice_t
* pv
= pat
->patternvoices
+ j
;
227 if(pv
->nbeats
> max_beats
) {
228 max_beats
= pv
->nbeats
;
229 pat
->longest_pv
= pv
;
234 ctx
->run
->prev
= NULL
;
235 ctx
->run
->curr
= config
->patterns
; // TODO: don't just use first-parsed pattern
237 ctx
->run
->sample_rate
= jack_get_sample_rate(client
);
239 ctx
->run
->transtate
= JackTransportStopped
;
241 if(ctx
->run
->curr
->bpm_relation
== RelativeToBase
) {
242 fprintf(stderr
,"First pattern must have an absolute tempo.\n");
245 ctx
->run
->base_beats_per_minute
= ctx
->run
->curr
->beats_per_minute
;
248 ctx
->next_pattern_func
=
249 (config
->next_pattern_func
? config
->next_pattern_func
: loop_all
);
254 /* Resets all patterns to the beginning of their playhead. May be
255 called from realtime thread.
257 Note that we don't change the "current" and "next" pattern pointers
258 since controllers may set those, and therefore the first pattern
259 may vary with each song start. Exception: if "current" is NULL,
260 the song is over and we have been requested to locate 0.
262 For the same reason, the base BPM is also not reset.
264 void qn_reset_playhead(qn_context_t
* ctx
) {
265 qn_config_t
* config
= ctx
->config
;
266 qn_runstate_t
* run
= ctx
->run
;
271 for(i
=0; i
<config
->npatterns
; i
++) {
272 qn_pattern_t
* pat
= config
->patterns
+ i
;
274 for(j
=0; j
<pat
->npatternvoices
; j
++) {
275 qn_patternvoice_t
* pv
= pat
->patternvoices
+ j
;
277 for(k
=0;k
<NEVENTSETS
;k
++) {
279 pv
->playhead_tmp
[k
] = 0;
284 // Timebase master values
288 run
->tbm_bar_start_tick
= 1;
289 run
->frame_in_tick
= 0;
291 // Song has finished, set back to start
294 run
->curr
= config
->patterns
;
298 void qn_free_config(qn_config_t
* cfg
) {
300 for(i
=0; i
<cfg
->nvoices
; i
++) {
301 cfg
->voices
[i
].port
= NULL
;
302 free(cfg
->voices
[i
].name
);
306 for(i
=0; i
<cfg
->noutports
; i
++) {
307 free(cfg
->outports
[i
].name
);
311 for(i
=0; i
<cfg
->npatterns
; i
++) {
312 qn_pattern_t
* p
= cfg
->patterns
+ i
;
314 if(p
->patternvoices
) {
315 if(p
->patternvoices
->nevents
) {
316 free(p
->patternvoices
->events
);
319 free(p
->patternvoices
);
329 void qn_free_context(qn_context_t
* ctx
) {
331 qn_config_t
* cfg
= ctx
->config
;
334 for(i
=0; i
<cfg
->noutports
; i
++) {
335 jack_port_unregister(ctx
->run
->client
, ctx
->run
->ports
[i
]->jackport
);
336 free(ctx
->run
->ports
[i
]);
338 free(ctx
->run
->ports
);
347 int cmp_outevent(const void* a
, const void* b
) {
348 const qn_outevent_t
* ea
= a
;
349 const qn_outevent_t
* eb
= b
;
351 // early message before late ones
352 if(ea
->at
< eb
->at
) {
354 } else if(ea
->at
> eb
->at
) {
358 // real-time (clock) messages over channel messages
359 int as
= ((ea
->data
[0] & 0xf8) == 0xf8);
360 int bs
= ((eb
->data
[0] & 0xf8) == 0xf8);
363 } else if(!as
&& bs
) {