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

Contents of /src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show annotations)
Sat Aug 18 07:43:54 2012 UTC (8 years, 1 month ago) by ben
File MIME type: text/plain
File size: 6070 byte(s)
begin some (runnable) MIDI related code in jack_process_calback
1 /* Copyright (c) 2012, Benoit Rouits <brouits@free.fr>
2 * Some rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
14 * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
17 * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
19 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <jack/jack.h>
32 #include <jack/midiport.h>
33
34 #include <config.h>
35 #include "graph.h"
36
37 #define MAX_VOICE 64
38 #define MAX_INST 128
39
40 #define error(str) fprintf(stderr, "[error]\t%s\n", str)
41
42 struct jack {
43 jack_client_t *client;
44 jack_transport_state_t state;
45 };
46
47 struct voice {
48 struct event* route;
49 int count;
50 int cur;
51 jack_time_t press;
52 };
53
54 struct instrument {
55 struct voice voices[MAX_VOICE];
56 jack_port_t *out;
57 void* out_buf;
58 int count;
59 struct graph *graph;
60 };
61
62 struct app {
63 struct instrument* instruments;
64 int count;
65 struct jack *jack;
66 };
67
68 static int jack_process_callback(jack_nframes_t nframes, void *ctx)
69 {
70 struct app *app;
71 jack_transport_state_t state;
72 jack_nframes_t last_frame_time;
73 int i, voice, inst;
74
75 app = ctx;
76
77 if (nframes <= 0)
78 return 0;
79
80 /* prepare all out buffers before writing into them */
81 for (i = 0; i < app->count; i++) {
82 void *port_buf = jack_port_get_buffer(app->instruments[i].out, nframes);
83 jack_midi_clear_buffer(port_buf);
84 app->instruments[i].out_buf = port_buf;
85 }
86
87 /* get transport state, act in consequence */
88
89 /* check end of all voices of all instruments */
90
91 /* go browse all voice states and send events */
92 for (i = 0; i < nframes; i++)
93 for (inst = 0; inst < app->count; inst++)
94 for (voice = 0; voice < app->instruments[inst].count; voice++) {
95 int *press = &app->instruments[inst].voices[voice].press;
96 int *cur = &app->instruments[inst].voices[voice].cur;
97 if (*cur >= app->instruments[inst].voices[voice].count)
98 continue;
99 struct event *ev = &app->instruments[inst].voices[voice].route[*cur];
100 unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, i, 3);
101 jack_time_t now = jack_get_time();
102 if (!buf)
103 return 0;
104
105 if (*press) { /* note must be released before passing to next event */
106 if (*press + ev->duration < now) {
107 buf[2] = ev->velocity;
108 buf[1] = ev->pitch;
109 buf[0] = 0x80; /* note off */
110 press = 0; /* release */
111 (*cur)++; /* go to next node */
112 fprintf(stderr, "off %d (%p)\n", ev->pitch, ev);
113 }
114 } else { /* this is a new node */
115 buf[2] = ev->velocity;
116 buf[1] = ev->pitch;
117 buf[0] = 0x90; /* note on */
118 *press = now;
119 fprintf(stderr, "on %d (%p)\n", ev->pitch, ev);
120 }
121 }
122
123 return 0;
124 }
125
126 static int jack_sync_callback(jack_transport_state_t state, jack_position_t *position, void *ctx)
127 {
128 struct instrument *instrument;
129
130 instrument = ctx;
131
132 if (state == JackTransportStarting) {
133 /* seek in paths (???) according to position->frame */
134 } else if (state == JackTransportStopped) {
135 /* pause */
136 }
137
138 return 1;
139 }
140
141 void jack_shutdown(void* ctx)
142 {
143 puts("jack vanished...");
144 }
145
146 int main (int argc, char *argv[])
147 {
148 struct app app;
149 struct jack jack;
150 struct instrument instrument;
151 struct graph *graph;
152 struct voice voice;
153
154 int i, err;
155
156 /* create random graph */
157 graph = graph_new(100);
158 graph_randomize2(graph, 3);
159
160 /* initialize solo instrument */
161 memset(&instrument, 0, sizeof(instrument));
162 instrument.graph = graph;
163 app.jack = &jack;
164 app.instruments = &instrument;
165 app.count = 1;
166
167 /* create a random route (lol) */
168 voice.route = &graph->nodes[0].event;
169 voice.count = 1;
170 instrument.voices[0] = voice;
171 instrument.count = 1;
172
173 /* mark it (...) */
174 app.instruments[0].voices[0].route[0].pitch = 42;
175 app.instruments[0].voices[0].route[0].duration = 42;
176
177 /* init jack */
178 jack.client = jack_client_open(PACKAGE_NAME, JackNullOption, NULL);
179 if (jack.client == NULL) {
180 error("could not connect to jackd");
181 exit(EXIT_FAILURE);
182 }
183
184 err = jack_set_process_callback(jack.client, jack_process_callback, &app);
185
186 if (err) {
187 error("could not set jack process callback");
188 exit(EXIT_FAILURE);
189 }
190
191 err = jack_set_sync_callback(jack.client, jack_sync_callback, &app);
192
193 if (err) {
194 error("could not set jack sync callback");
195 exit(EXIT_FAILURE);
196 }
197
198 jack_on_shutdown(jack.client, jack_shutdown, &app);
199
200 /* allocate one jack port per instrument (midi outs) */
201 for (i = 0; i < app.count; i++) {
202 char name[32];
203 snprintf(name, 32, "out %d", i);
204 app.instruments[i].out = jack_port_register(jack.client, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
205 if (app.instruments[i].out == NULL) {
206 error("could not register a jack midi out port");
207 exit(EXIT_FAILURE);
208 }
209 }
210
211 /* activate jack */
212 if (jack_activate(jack.client)) {
213 error("could not activate jack client");
214 exit(EXIT_FAILURE);
215 }
216
217 /* start playing (event loop) */
218 sleep(1);
219
220 /* close jack */
221 jack_client_close (jack.client);
222
223 /* exit */
224 graph_destroy(graph);
225
226 exit(EXIT_SUCCESS);
227 }

  ViewVC Help
Powered by ViewVC 1.1.26