/[paths]/src/jack.c
ViewVC logotype

Contents of /src/jack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 63 - (show annotations)
Sun Aug 26 03:23:50 2012 UTC (6 years, 10 months ago) by ben
File MIME type: text/plain
File size: 5923 byte(s)
highlight nodes while playing
1 #include <assert.h>
2 #include <jack/jack.h>
3 #include <jack/midiport.h>
4
5 #include "main.h"
6 #include "egg_node.h"
7
8 void jack_info_function(const char* str)
9 {
10 }
11
12 void jack_error_function(const char* str)
13 {
14 }
15
16 static int send_prog_change(struct app *app, int inst, int frame)
17 {
18 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, frame, 2);
19 if (!buf) {
20 error("no memory, event lost");
21 return 1;
22 }
23 buf[1] = app->instruments[inst].prog;
24 buf[0] = 0xc0|app->instruments[inst].chan;
25 return 0;
26 }
27
28 void paint_note_on(struct app *app, struct event *ev)
29 {
30 int i;
31 for (i = 0; i < app->graph->count; i++) {
32 if (&app->graph->nodes[i].event == ev)
33 break;
34 }
35
36 assert(i < app->graph->count);
37 if (app->view && app->view->completed && app->view->populated) {
38 if (!ev->ref)
39 egg_node_set_color(app->view->nodes[i], 0.0, 0.0, 0.0);
40 ev->ref++;
41 }
42 }
43
44 void paint_note_off(struct app *app, struct event *ev)
45 {
46 int i;
47 for (i = 0; i < app->graph->count; i++) {
48 if (&app->graph->nodes[i].event == ev)
49 break;
50 }
51
52 assert(i < app->graph->count);
53 if (app->view && app->view->completed && app->view->populated) {
54 if (ev->ref == 1)
55 egg_node_set_color(app->view->nodes[i], 1.0, 1.0, 1.0);
56 if (ev->ref)
57 ev->ref--;
58 }
59 }
60
61 int send_note_off(struct app *app, int inst, int frame, struct event *ev)
62 {
63 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, frame, 3);
64 if (!buf) {
65 error("no memory, event lost");
66 return 1;
67 }
68 buf[2] = ev->velocity;
69 buf[1] = ev->pitch;
70 buf[0] = 0x80|app->instruments[inst].chan; /* note off */
71 fprintf(stderr, "off %d (%p)\n", ev->pitch, ev);
72 return 0;
73 }
74
75 int send_note_on(struct app *app, int inst, int frame, struct event *ev)
76 {
77 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, frame, 3);
78 if (!buf) {
79 error("no memory, event lost");
80 return 1;
81 }
82 buf[2] = ev->velocity;
83 buf[1] = ev->pitch;
84 buf[0] = 0x90|app->instruments[inst].chan; /* note on */
85 fprintf(stderr, "on %d (%p)\n", ev->pitch, ev);
86 return 0;
87 }
88
89 int broadcast_note_off(struct app *app, jack_nframes_t nframes)
90 {
91 int inst, voice;
92
93 for (inst = 0; inst < app->count; inst++) {
94 for (voice = 0; voice < app->instruments[inst].count; voice ++) {
95 if (app->instruments[inst].voices[voice].press) {
96 int cur = app->instruments[inst].voices[voice].cur;
97 struct event *ev = app->instruments[inst].voices[voice].route[cur];
98 send_note_off(app, inst, 0, ev);
99 }
100 }
101 }
102 }
103
104 int jack_process_callback(jack_nframes_t nframes, void *ctx)
105 {
106 struct app *app;
107 jack_transport_state_t state;
108 int i, voice, inst;
109
110 app = ctx;
111
112 if (nframes <= 0) {
113 error("called process w/o frames");
114 return 0;
115 }
116
117 /* prepare all out buffers before writing into them */
118 for (i = 0; i < app->count; i++) {
119 void *port_buf = jack_port_get_buffer(app->instruments[i].out, nframes);
120 jack_midi_clear_buffer(port_buf);
121 app->instruments[i].out_buf = port_buf;
122 }
123
124 /* get transport state, act in consequence */
125 state = jack_transport_query(app->jack->client, NULL);
126 if (state == JackTransportStopped) {
127 if (app->jack->state == JackTransportRolling) {
128 broadcast_note_off(app, nframes);
129 }
130 app->jack->state = state;
131 return 0;
132 }
133 app->jack->state = state;
134
135 /* check end of all voices of all instruments */
136 if (app->end >= app->count)
137 return 0;
138
139 /* go browse all voice states and send events */
140 for (i = 0; i < nframes; i++) {
141 if (app->end >= app->count) {
142 fprintf(stderr, "tune ended (%d instruments)\n", app->end);
143 return 0;
144 }
145 for (inst = 0; inst < app->count; inst++) {
146 if (app->instruments[inst].end >= app->instruments[inst].count) {
147 if (app->instruments[inst].end == app->instruments[inst].count) {
148 app->end++;
149 fprintf(stderr, "instrument %d ended (%d voices)\n", inst, app->instruments[inst].end);
150 app->instruments[inst].end++; /* do not pass here again */
151 }
152 continue;
153 }
154 for (voice = 0; voice < app->instruments[inst].count; voice++) {
155 jack_time_t *press = &app->instruments[inst].voices[voice].press;
156 int *cur = &app->instruments[inst].voices[voice].cur;
157 struct event *ev = app->instruments[inst].voices[voice].route[*cur];
158 jack_time_t now = jack_get_time();
159
160 if (*cur >= app->instruments[inst].voices[voice].count) {
161 if (*cur == app->instruments[inst].voices[voice].count) {
162 app->instruments[inst].end++;
163 fprintf(stderr, "instr. %d: voice %d ended (%d notes)\n", inst, voice, *cur);
164 (*cur)++; /* do not pass here again */
165 }
166 continue;
167 }
168
169
170 if (*press) { /* note must be released before passing to next note */
171 if (*press + ev->duration <= now) {
172 /* send a note off */
173 paint_note_off(app, ev);
174 send_note_off(app, inst, i, ev);
175 *press = 0; /* release */
176 (*cur)++; /* go to next node */
177 } else {
178 /* nothing to do for now */
179 }
180 } else { /* this is a new note */
181 /* set program change on start only */
182 if (app->instruments[inst].prog != app->instruments[inst].last_prog) {
183 send_prog_change(app, inst, i);
184 app->instruments[inst].last_prog = app->instruments[inst].prog;
185 }
186 paint_note_on(app, ev);
187 send_note_on(app, inst, i, ev);
188 *press = now;
189 }
190 }
191 }
192 }
193
194 return 0;
195 }
196 int jack_sync_callback(jack_transport_state_t state, jack_position_t *position, void *ctx)
197 {
198 struct app *app;
199
200 app = ctx;
201
202 if (state == JackTransportStarting) {
203 /* seek in paths (???) according to position->frame */
204 } else if (state == JackTransportStopped) {
205 if (position->frame == 0) {
206 /* reset voices */
207 int inst, voice;
208 for (inst = 0; inst < app->count; inst++) {
209 for (voice = 0; voice < app->instruments[inst].count; voice++) {
210 app->instruments[inst].voices[voice].cur = 0;
211 app->instruments[inst].voices[voice].press = 0;
212 }
213 }
214 }
215 }
216
217 return 1;
218 }
219
220 void jack_shutdown(void* ctx)
221 {
222 puts("jack vanished...");
223 }

  ViewVC Help
Powered by ViewVC 1.1.26