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

Annotation of /src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations)
Sat Aug 18 08:47:41 2012 UTC (8 years, 1 month ago) by ben
File MIME type: text/plain
File size: 6731 byte(s)
better dummy jack_process_callback
1 ben 18 /* 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 ben 6 #include <stdio.h>
28 ben 15 #include <stdlib.h>
29     #include <string.h>
30    
31     #include <jack/jack.h>
32     #include <jack/midiport.h>
33    
34     #include <config.h>
35 ben 6 #include "graph.h"
36    
37 ben 23 #define MAX_VOICE 64
38     #define MAX_INST 128
39 ben 15
40 ben 18 #define error(str) fprintf(stderr, "[error]\t%s\n", str)
41 ben 15
42     struct jack {
43     jack_client_t *client;
44 ben 21 jack_transport_state_t state;
45 ben 15 };
46    
47 ben 21 struct voice {
48     struct event* route;
49 ben 16 int count;
50 ben 15 int cur;
51 ben 24 jack_time_t press;
52 ben 15 };
53    
54 ben 21 struct instrument {
55 ben 23 struct voice voices[MAX_VOICE];
56 ben 25 int count;
57     int end;
58    
59 ben 24 jack_port_t *out;
60     void* out_buf;
61 ben 25
62 ben 15 struct graph *graph;
63 ben 21 };
64    
65     struct app {
66     struct instrument* instruments;
67     int count;
68 ben 25 int end;
69    
70 ben 15 struct jack *jack;
71     };
72    
73     static int jack_process_callback(jack_nframes_t nframes, void *ctx)
74 ben 11 {
75 ben 21 struct app *app;
76     jack_transport_state_t state;
77 ben 24 int i, voice, inst;
78 ben 15
79 ben 21 app = ctx;
80 ben 15
81 ben 25 if (nframes <= 0) {
82     error("called process w/o frames");
83 ben 15 return 0;
84 ben 25 }
85 ben 15
86 ben 24 /* prepare all out buffers before writing into them */
87     for (i = 0; i < app->count; i++) {
88     void *port_buf = jack_port_get_buffer(app->instruments[i].out, nframes);
89     jack_midi_clear_buffer(port_buf);
90     app->instruments[i].out_buf = port_buf;
91     }
92    
93 ben 21 /* get transport state, act in consequence */
94 ben 24
95 ben 21 /* check end of all voices of all instruments */
96 ben 25 if (app->end >= app->count)
97     return 0;
98 ben 24
99 ben 21 /* go browse all voice states and send events */
100 ben 25 for (i = 0; i < nframes; i++) {
101     if (app->end >= app->count) {
102     fprintf(stderr, "tune ended (%d instruments)\n", app->end);
103     return 0;
104     }
105     for (inst = 0; inst < app->count; inst++) {
106     if (app->instruments[inst].end >= app->instruments[inst].count) {
107     app->end++;
108     fprintf(stderr, "instrument %d ended (%d voices)\n", inst, app->instruments[inst].end);
109     continue;
110     }
111 ben 24 for (voice = 0; voice < app->instruments[inst].count; voice++) {
112 ben 25 jack_time_t *press = &app->instruments[inst].voices[voice].press;
113 ben 24 int *cur = &app->instruments[inst].voices[voice].cur;
114 ben 25 if (*cur >= app->instruments[inst].voices[voice].count) {
115     app->instruments[inst].end++;
116     fprintf(stderr, "voice %d ended (%d notes)\n", voice, *cur);
117 ben 24 continue;
118 ben 25 }
119 ben 24 struct event *ev = &app->instruments[inst].voices[voice].route[*cur];
120     unsigned char *buf = jack_midi_event_reserve(app->instruments[inst].out_buf, i, 3);
121 ben 25 if (!buf) {
122     error("no memory, note lost");
123 ben 24 return 0;
124 ben 25 }
125 ben 16
126 ben 25 jack_time_t now = jack_get_time();
127    
128     if (*press) { /* note must be released before passing to next note */
129 ben 24 if (*press + ev->duration < now) {
130     buf[2] = ev->velocity;
131     buf[1] = ev->pitch;
132     buf[0] = 0x80; /* note off */
133     press = 0; /* release */
134     (*cur)++; /* go to next node */
135     fprintf(stderr, "off %d (%p)\n", ev->pitch, ev);
136     }
137 ben 25 } else { /* this is a new note */
138 ben 24 buf[2] = ev->velocity;
139     buf[1] = ev->pitch;
140     buf[0] = 0x90; /* note on */
141     *press = now;
142     fprintf(stderr, "on %d (%p)\n", ev->pitch, ev);
143     }
144     }
145 ben 25 }
146     }
147 ben 24
148 ben 15 return 0;
149     }
150    
151     static int jack_sync_callback(jack_transport_state_t state, jack_position_t *position, void *ctx)
152     {
153 ben 21 struct instrument *instrument;
154 ben 15
155 ben 21 instrument = ctx;
156 ben 15
157     if (state == JackTransportStarting) {
158 ben 21 /* seek in paths (???) according to position->frame */
159 ben 15 } else if (state == JackTransportStopped) {
160     /* pause */
161 ben 11 }
162 ben 15
163     return 1;
164 ben 11 }
165    
166 ben 21 void jack_shutdown(void* ctx)
167 ben 17 {
168     puts("jack vanished...");
169     }
170    
171 ben 15 int main (int argc, char *argv[])
172 ben 6 {
173 ben 25 struct graph *graph;
174 ben 21 struct instrument instrument;
175     struct voice voice;
176 ben 25 struct jack jack;
177     struct app app;
178 ben 6
179 ben 24 int i, err;
180 ben 15
181     /* create random graph */
182 ben 16 graph = graph_new(100);
183 ben 15 graph_randomize2(graph, 3);
184    
185 ben 25 /* initialize a solo instrument */
186 ben 21 memset(&instrument, 0, sizeof(instrument));
187     instrument.graph = graph;
188 ben 25
189     /* initialize application context */
190     memset(&app, 0, sizeof(app));
191 ben 21 app.jack = &jack;
192     app.instruments = &instrument;
193     app.count = 1;
194 ben 15
195 ben 21 /* create a random route (lol) */
196 ben 25 memset(&voice, 0, sizeof(voice));
197 ben 21 voice.route = &graph->nodes[0].event;
198     voice.count = 1;
199     instrument.voices[0] = voice;
200     instrument.count = 1;
201 ben 15
202 ben 21 /* mark it (...) */
203     app.instruments[0].voices[0].route[0].pitch = 42;
204 ben 24 app.instruments[0].voices[0].route[0].duration = 42;
205 ben 21
206 ben 15 /* init jack */
207     jack.client = jack_client_open(PACKAGE_NAME, JackNullOption, NULL);
208     if (jack.client == NULL) {
209     error("could not connect to jackd");
210     exit(EXIT_FAILURE);
211     }
212    
213 ben 21 err = jack_set_process_callback(jack.client, jack_process_callback, &app);
214 ben 15
215     if (err) {
216     error("could not set jack process callback");
217     exit(EXIT_FAILURE);
218     }
219    
220 ben 21 err = jack_set_sync_callback(jack.client, jack_sync_callback, &app);
221 ben 15
222     if (err) {
223     error("could not set jack sync callback");
224     exit(EXIT_FAILURE);
225     }
226    
227 ben 21 jack_on_shutdown(jack.client, jack_shutdown, &app);
228 ben 17
229 ben 24 /* allocate one jack port per instrument (midi outs) */
230     for (i = 0; i < app.count; i++) {
231     char name[32];
232     snprintf(name, 32, "out %d", i);
233     app.instruments[i].out = jack_port_register(jack.client, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
234     if (app.instruments[i].out == NULL) {
235     error("could not register a jack midi out port");
236     exit(EXIT_FAILURE);
237     }
238 ben 15 }
239    
240     /* activate jack */
241     if (jack_activate(jack.client)) {
242     error("could not activate jack client");
243     exit(EXIT_FAILURE);
244     }
245    
246     /* start playing (event loop) */
247 ben 24 sleep(1);
248 ben 15
249     /* close jack */
250 ben 16 jack_client_close (jack.client);
251 ben 15
252     /* exit */
253 ben 10 graph_destroy(graph);
254 ben 15
255     exit(EXIT_SUCCESS);
256 ben 6 }

  ViewVC Help
Powered by ViewVC 1.1.26