1
2 /*
3 * Diverse Bristol audio routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21 /*
22 * This will be a linear drawbar. Takes a bitmap and locates it according to
23 * input from the mouse/keyboard. Previous positions need to be unmapped, since
24 * there is total repositioning of the image bitmap.
25 */
26
27 #include "brightoninternals.h"
28
29 int
destroyModWheel(brightonDevice * dev)30 destroyModWheel(brightonDevice *dev)
31 {
32 printf("destroyModWheel()\n");
33
34 if (dev->image)
35 brightonFreeBitmap(dev->bwin, dev->image);
36 dev->image = NULL;
37
38 return(0);
39 }
40
41 static int
displaymodwheel(brightonDevice * dev)42 displaymodwheel(brightonDevice *dev)
43 {
44 brightonIResource *panel;
45 float displayvalue;
46
47 if (dev->bwin->app->resources[dev->panel].flags & BRIGHTON_WITHDRAWN)
48 return(0);
49
50 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
51 & BRIGHTON_WITHDRAWN)
52 return(0);
53
54 panel = &dev->bwin->app->resources[dev->panel];
55
56 /*
57 * Build up a smooth position for the bar. We may need to adjust this based
58 * on the to/from values.
59 */
60 if (dev->value == dev->lastvalue)
61 return(0);
62
63 displayvalue = dev->value;
64
65 /*
66 brightonFinalRender(dev->bwin,
67 dev->x + dev->bwin->app->resources[dev->panel].sx,
68 dev->y + dev->lastposition + dev->bwin->app->resources[dev->panel].sy,
69 dev->width, dev->height / 4);
70 */
71
72 /*
73 * This seems odd, the vertical flag refers to the scrolled item, not the
74 * direction of movement. Perhaps that should change as the direction of
75 * movement is counterintuitive
76 */
77 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
78 & BRIGHTON_VERTICAL)
79 {
80 if (dev->lastposition >= 0)
81 {
82 brightonDevUndraw(dev->bwin, dev->bwin->dlayer,
83 dev->x + ((int) dev->lastposition)
84 + dev->bwin->app->resources[dev->panel].sx,
85 dev->y + dev->bwin->app->resources[dev->panel].sy,
86 dev->width / 8, dev->height);
87 brightonRenderShadow(dev, 1);
88 }
89
90 dev->position = displayvalue * (dev->width - dev->width / 4);
91
92 /*
93 * Only draw fixed number of steps. Panned. Just draw it.....
94 */
95 brightonStretch(dev->bwin, dev->image,
96 dev->bwin->dlayer,
97 (int)(dev->x + dev->position
98 + dev->bwin->app->resources[dev->panel].sx),
99 dev->y + dev->bwin->app->resources[dev->panel].sy,
100 dev->width / 8, dev->height, 1);
101
102 brightonRenderShadow(dev, 0);
103
104 /*
105 * And request the panel to put this onto the respective image.
106 */
107 if (dev->position > dev->lastposition)
108 {
109 brightonFinalRender(dev->bwin,
110 dev->x + dev->lastposition
111 + dev->bwin->app->resources[dev->panel].sx,
112 dev->y + dev->bwin->app->resources[dev->panel].sy,
113 dev->width * 2,
114 dev->position - dev->lastposition + (dev->width >> 2)
115 + (dev->height >> 1));
116 } else {
117 brightonFinalRender(dev->bwin,
118 dev->x + dev->position
119 + dev->bwin->app->resources[dev->panel].sx,
120 dev->y + dev->bwin->app->resources[dev->panel].sy,
121 dev->width * 2 + 1,
122 dev->lastposition - dev->position + (dev->width >> 2)
123 + (dev->height >> 1));
124 }
125 } else {
126 brightonBitmap image2;
127
128 dev->position = displayvalue * (dev->height - dev->height / 4);
129
130 /*
131 printf("modwheel motion %i %i, %i %i, %i %i: %f\n",
132 event->x, event->y, dev->x, dev->y, dev->width, dev->height, dev->value);
133 */
134
135 /*
136 * Don't need to undraw as we have to paint the whole lot anyway
137 *
138 brightonDevUndraw(dev->bwin, dev->bwin->dlayer,
139 dev->x + dev->bwin->app->resources[dev->panel].sx,
140 dev->y + dev->bwin->app->resources[dev->panel].sy,
141 dev->width, dev->height);
142
143 * For the ModWheel scale we need a different transform. The bitmap
144 * wants to be stretched onto the destination, but only part of it
145 * depending on the current value.
146 *
147 * We have to dynamically rebuild the bitmap as well so that we
148 * get it to move rather than just be placed.
149 */
150
151 image2.flags = dev->image2->flags;
152 image2.width = dev->image2->width;
153 image2.ncolors = dev->image2->ncolors;
154 image2.ctabsize = dev->image2->ctabsize;
155 image2.istatic = dev->image2->istatic;
156 image2.ostatic = dev->image2->ostatic;
157 image2.colormap = dev->image2->colormap;
158 image2.name = dev->image2->name;
159
160 image2.height = dev->image2->height * 9 / 16;
161 image2.pixels = &dev->image2->pixels[image2.width *
162 (int) (((float) dev->image2->height * 7/16) * (1.0 - dev->value))];
163
164 if (image2.height != 0)
165 brightonStretch(dev->bwin, &image2,
166 dev->bwin->dlayer,
167 (int) (dev->x + dev->bwin->app->resources[dev->panel].sx),
168 (int) (dev->y + dev->bwin->app->resources[dev->panel].sy),
169 dev->width, dev->height, 0);
170
171 brightonFinalRender(dev->bwin,
172 dev->x + dev->bwin->app->resources[dev->panel].sx,
173 dev->y + dev->bwin->app->resources[dev->panel].sy,
174 dev->width, (int) dev->height);
175 }
176
177 dev->lastvalue = dev->value;
178 dev->lastposition = dev->position;
179
180 return(0);
181 }
182
183 static int
considercallback(brightonDevice * dev)184 considercallback(brightonDevice *dev)
185 {
186 brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
187 float callvalue;
188
189 if (dev->bwin->flags & BRIGHTON_NO_DRAW)
190 return(0);
191
192 if (dev->value > 1.0)
193 dev->value = 1.0;
194 else if (dev->value < 0)
195 dev->value = 0.0;
196
197 /*
198 * Due to the co-ordinate system, if we do NOT have the reverse flags
199 * then we need to reverse the value.
200 */
201 if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
202 & BRIGHTON_REVERSE) == 0)
203 callvalue = 1.0 - dev->value;
204 else
205 callvalue = dev->value;
206
207 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].to != 1.0)
208 {
209 callvalue =
210 (callvalue
211 * dev->bwin->app->resources[dev->panel].devlocn[dev->index].to);
212
213 if ((callvalue - ((int) callvalue)) > 0.5)
214 callvalue = ((float) ((int) callvalue) + 1);
215 else
216 callvalue = ((float) ((int) callvalue));
217 }
218
219 if (dev->lastvalue != dev->value)
220 {
221 if (panel->devlocn[dev->index].callback)
222 {
223 panel->devlocn[dev->index].callback(dev->bwin, dev->panel,
224 dev->index, callvalue);
225 } else {
226 if (panel->callback)
227 panel->callback(dev->bwin, dev->panel, dev->index, callvalue);
228 }
229 }
230 return(0);
231 }
232
233 static int cx, cy;
234 static float sval;
235
236 static int
configure(brightonDevice * dev,brightonEvent * event)237 configure(brightonDevice *dev, brightonEvent *event)
238 {
239 /* printf("configureModWheel(%i, %f)\n", event->command, event->value); */
240
241 if (event->command == -1)
242 return(-1);
243
244 if (event->command == BRIGHTON_RESIZE)
245 {
246 dev->originx = event->x;
247 dev->originy = event->y;
248
249 dev->x = event->x;
250 dev->y = event->y;
251 dev->width = event->w;
252 dev->height = event->h;
253
254 /*
255 * We should now rework our parent understanding of our window, since
256 * it will have altered. NOT NECESSARY FOR SCALE.
257 brightonPanelLocation(dev->bwin,
258 dev->panel, dev->index, dev->x, dev->y, dev->width, dev->height);
259
260 considercallback(dev);
261 */
262
263 /*
264 * Highlights need to be rendered dynamically in displaymodwheel().
265 */
266
267 dev->lastvalue = -1;
268 displaymodwheel(dev);
269
270 return(0);
271 }
272
273 if (event->command == BRIGHTON_KEYRELEASE)
274 {
275 /*
276 * This is a little bit 'happens they work'. We should fix these key
277 * mappings for keycodes.
278 */
279 switch(event->key) {
280 default:
281 break;
282 case 37:
283 case 109:
284 case 65508:
285 case 65507:
286 dev->flags &= ~BRIGHTON_CONTROLKEY;
287 cx = cy = sval = -1;
288 break;
289 case 50:
290 case 62:
291 case 65505:
292 dev->flags &= ~BRIGHTON_SHIFTKEY;
293 break;
294 }
295 }
296
297 if (event->command == BRIGHTON_BUTTONPRESS)
298 {
299 /*
300 * This is hard coded, it calls back to the GUI. This is incorrect as
301 * the callback dispatcher should be requested by the GUI.
302 *
303 * Perhaps the MIDI code should actually be in the same library? Why
304 * does the GUI need to know about this?
305 */
306 if (event->key == BRIGHTON_BUTTON2)
307 brightonRegisterController(dev);
308
309 return(0);
310 }
311
312 if (event->command == BRIGHTON_BUTTONRELEASE)
313 {
314 cx = cy = sval = -1;
315 dev->flags &= ~BRIGHTON_CONTROLKEY;
316
317 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
318 & BRIGHTON_CENTER)
319 {
320 dev->value = 0.5;
321
322 considercallback(dev);
323
324 displaymodwheel(dev);
325 }
326
327 return(0);
328 }
329
330 if (event->command == BRIGHTON_KEYPRESS)
331 {
332 switch(event->key) {
333 default:
334 break;
335 case 37:
336 case 109:
337 case 65508:
338 case 65507:
339 cx = event->x;
340 cy = event->y;
341 sval = dev->value;
342 dev->flags |= BRIGHTON_CONTROLKEY;
343 break;
344 case 50:
345 case 62:
346 case 65505:
347 dev->flags |= BRIGHTON_SHIFTKEY;
348 break;
349 case 0x6a:
350 case 0xff54:
351 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags & BRIGHTON_VERTICAL)
352 {
353 if (dev->flags & BRIGHTON_SHIFTKEY)
354 dev->value -= ((float) 256) / 16384;
355 else
356 dev->value -= ((float) 1) / 16384;
357 } else {
358 if (dev->flags & BRIGHTON_SHIFTKEY)
359 dev->value += ((float) 256) / 16384;
360 else
361 dev->value += ((float) 1) / 16384;
362 }
363 break;
364 case 0x6b:
365 case 0xff52:
366 /*if (dev->flags & BRIGHTON_VERTICAL) */
367 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags & BRIGHTON_VERTICAL)
368 {
369 if (dev->flags & BRIGHTON_SHIFTKEY)
370 dev->value += ((float) 256) / 16384;
371 else
372 dev->value += ((float) 1) / 16384;
373 } else {
374 if (dev->flags & BRIGHTON_SHIFTKEY)
375 dev->value -= ((float) 256) / 16384;
376 else
377 dev->value -= ((float) 1) / 16384;
378 }
379 break;
380 case 0xff51:
381 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags & BRIGHTON_VERTICAL)
382 {
383 if (dev->flags & BRIGHTON_SHIFTKEY)
384 dev->value -= ((float) 2048) / 16384;
385 else
386 dev->value -= ((float) 32) / 16384;
387 } else {
388 if (dev->flags & BRIGHTON_SHIFTKEY)
389 dev->value += ((float) 2048) / 16384;
390 else
391 dev->value += ((float) 32) / 16384;
392 }
393 break;
394 case 0xff53:
395 /*if (dev->flags & BRIGHTON_VERTICAL) */
396 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags & BRIGHTON_VERTICAL)
397 {
398 if (dev->flags & BRIGHTON_SHIFTKEY)
399 dev->value += ((float) 2048) / 16384;
400 else
401 dev->value += ((float) 32) / 16384;
402 } else {
403 if (dev->flags & BRIGHTON_SHIFTKEY)
404 dev->value -= ((float) 2048) / 16384;
405 else
406 dev->value -= ((float) 32) / 16384;
407 }
408 break;
409 }
410
411 considercallback(dev);
412
413 displaymodwheel(dev);
414 }
415
416 if (event->command == BRIGHTON_MOTION)
417 {
418 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
419 & BRIGHTON_VERTICAL)
420 {
421 /*
422 * Need to add in an optional central dead spot. This should be a
423 * small fraction of either side of the bar. It will be where
424 * position deviates from mouse location.
425 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
426 & BRIGHTON_NOTCH)
427 {
428 } else
429 */
430 if (dev->flags & BRIGHTON_CONTROLKEY)
431 {
432 float deltax;
433
434 if (cx == -1)
435 {
436 sval = dev->value;
437 cx = event->x;
438 cy = event->y;
439 }
440
441 deltax = ((float) (event->x - cx)) / 16383.0f;
442
443 dev->value = sval + deltax;
444 } else if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags & BRIGHTON_NOTCH)
445 {
446 /*
447 * When we are passing zero we should hold for a bit.
448 */
449 dev->value = (((float) (event->x + 5 - dev->x - (dev->width / 8)))
450 / (dev->width - dev->width / 4));
451
452 if (dev->value > 0.6)
453 dev->value -= 0.1;
454 else if (dev->value < 0.4)
455 dev->value += 0.1;
456 else
457 dev->value = 0.5;
458 } else
459 dev->value = (((float) (event->x + 5 - dev->x - (dev->width / 8)))
460 / (dev->width - dev->width / 4));
461 } else {
462 if (dev->flags & BRIGHTON_CONTROLKEY)
463 {
464 float deltax;
465
466 if (cx == -1)
467 {
468 sval = dev->value;
469 cx = event->x;
470 cy = event->y;
471 }
472
473 deltax = ((float) (event->y - cy)) / 16383.0f;
474
475 dev->value = sval + deltax;
476 } else if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags & BRIGHTON_NOTCH)
477 {
478 dev->value = (((float) (event->y - dev->y - (dev->height / 8)))
479 / (dev->height - dev->height / 4));
480
481 if (dev->value > 0.6)
482 dev->value -= 0.1;
483 else if (dev->value < 0.4)
484 dev->value += 0.1;
485 else
486 dev->value = 0.5;
487 } else
488 dev->value = (((float) (event->y - dev->y - (dev->height / 8)))
489 / (dev->height - dev->height / 4));
490 }
491
492 /*
493 * We now need to consider rounding this to the resolution of this
494 * device. If the max value is not 1.0 then we need to put fixed steps
495 * into our new device value.
496 */
497 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].to != 1.0)
498 {
499 dev->value = (float) ((int)
500 (dev->value
501 * dev->bwin->app->resources[dev->panel].devlocn[dev->index].to))
502 / dev->bwin->app->resources[dev->panel].devlocn[dev->index].to;
503 }
504
505 considercallback(dev);
506
507 displaymodwheel(dev);
508
509 return(0);
510 }
511
512 if (event->command == BRIGHTON_PARAMCHANGE)
513 {
514 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
515 & BRIGHTON_REVERSE)
516 dev->value = event->value
517 / dev->bwin->app->resources[dev->panel].devlocn[dev->index].to;
518 else {
519 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].to
520 != 1.0)
521 {
522 dev->value =
523 (dev->bwin->app->resources[dev->panel].devlocn[dev->index].to - event->value)
524 / dev->bwin->app->resources[dev->panel].devlocn[dev->index].to;
525 } else {
526 dev->value = (1.0 - event->value) /
527 dev->bwin->app->resources[dev->panel].devlocn[dev->index].to;
528 }
529 }
530
531 considercallback(dev);
532
533 displaymodwheel(dev);
534
535 return(0);
536 }
537 return(0);
538 }
539
540 int *
createModWheel(brightonWindow * bwin,brightonDevice * dev,int index,char * bitmap)541 createModWheel(brightonWindow *bwin, brightonDevice *dev, int index, char *bitmap)
542 {
543 /* printf("createModWheel(%s)\n", bitmap); */
544
545 dev->destroy = destroyModWheel;
546 dev->configure = configure;
547 dev->index = index;
548
549 dev->bwin = bwin;
550
551 if (bitmap == 0)
552 {
553 if (dev->image)
554 brightonFreeBitmap(bwin, dev->image);
555 /*
556 * Open the default bitmap
557 */
558 if (bwin->app->resources[dev->panel].devlocn[dev->index].image != 0)
559 dev->image =
560 bwin->app->resources[dev->panel].devlocn[dev->index].image;
561 else
562 dev->image = brightonReadImage(bwin, "bitmaps/knobs/slider1.xpm");
563 } else {
564 if (dev->image)
565 brightonFreeBitmap(bwin, dev->image);
566 dev->image = brightonReadImage(bwin, bitmap);
567 }
568
569 if (bwin->app->resources[dev->panel].devlocn[dev->index].flags &
570 BRIGHTON_HSCALE)
571 {
572 if (dev->image2)
573 brightonFreeBitmap(bwin, dev->image2);
574 dev->image2 = brightonReadImage(bwin, bitmap);
575 }
576
577 /*
578 * These will force an update when we first display ourselves.
579 */
580 if (bwin->app->resources[dev->panel].devlocn[dev->index].flags
581 & BRIGHTON_CENTER)
582 dev->value = 0.5;
583 else
584 dev->value = 0;
585
586 dev->value = 0.500001;
587
588 dev->lastvalue = -1;
589 dev->lastposition = 0;
590
591 return(0);
592 }
593
594