audiofile support + improved sample rate support + results of a -Wall -Werr
[terminatorX.git] / src / tX_flash.c
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2002  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_flash.c
20  
21     Description: This contains the implementation of the tx_flash_flash widget.
22 */    
23
24 #include <math.h>
25
26 #include <gtk/gtkwindow.h>
27 #define IS_TX_FLASH 1
28 #include "tX_flash.h"
29 #include "tX_types.h"
30 #include "tX_global.h"
31 #include <malloc.h>
32
33 #ifndef WIN32
34 #include <unistd.h>
35 #endif
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif /* __cplusplus */
40
41 #define MAX_VALUE 32767
42 #define RED_BORDER 25000
43 #define TX_FLASH_DEFAULT_SIZE_X 17
44 #define TX_FLASH_DEFAULT_SIZE_Y 30
45 #define DY 5
46 #define DX 5
47 #define DMINIX 2
48 #define S_MINIX 2
49 #define L_MINIX 3
50 #define DLEVEL 3
51 #define MAX_MAX_CYCLES 20;
52
53 /* pre dec */
54 static void gtk_tx_flash_class_init (GtkTxFlashClass *);
55 static void gtk_tx_flash_init (GtkTxFlash *tx_flash);
56 GtkWidget* gtk_tx_flash_new ();
57 static void gtk_tx_flash_destroy (GtkObject *object);
58 static void gtk_tx_flash_realize (GtkWidget *widget);
59 static void gtk_tx_flash_size_request (GtkWidget *widget, GtkRequisition *requisition);
60 static void gtk_tx_flash_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
61 static gint gtk_tx_flash_expose (GtkWidget *widget, GdkEventExpose *event);
62 //static void gtk_tx_flash_prepare (GtkWidget *widget);
63 //static void gtk_tx_flash_set_level(GtkWidget *widget, f_prec new_value);
64
65 /* Local data */
66
67 static GtkWidgetClass *parent_class = NULL;
68
69 guint
70 gtk_tx_flash_get_type ()
71 {
72   static guint tx_flash_type = 0;
73
74   if (!tx_flash_type)
75     {
76       GtkTypeInfo tx_flash_info =
77       {
78         "GtkTxFlash",
79         sizeof (GtkTxFlash),
80         sizeof (GtkTxFlashClass),
81         (GtkClassInitFunc) gtk_tx_flash_class_init,
82         (GtkObjectInitFunc) gtk_tx_flash_init,
83         /* reserved */ NULL,
84         /* reserved */ NULL,
85         /* reserved */ NULL
86       };
87
88       tx_flash_type = gtk_type_unique (gtk_widget_get_type (), &tx_flash_info);
89     }
90
91   return tx_flash_type;
92 }
93
94 static void
95 gtk_tx_flash_class_init (GtkTxFlashClass *gclass)
96 {
97   GtkObjectClass *object_class;
98   GtkWidgetClass *widget_class;
99
100   object_class = (GtkObjectClass*) gclass;
101   widget_class = (GtkWidgetClass*) gclass;
102
103   parent_class = gtk_type_class (gtk_widget_get_type ());
104
105   object_class->destroy = gtk_tx_flash_destroy;
106
107   widget_class->realize = gtk_tx_flash_realize;
108   widget_class->expose_event = gtk_tx_flash_expose;
109   widget_class->size_request = gtk_tx_flash_size_request;
110   widget_class->size_allocate = gtk_tx_flash_size_allocate;
111 //  widget_class->button_press_event = gtk_tx_flash_button_press;
112 //  widget_class->button_release_event = gtk_tx_flash_button_release;
113 //  widget_class->motion_notify_event = gtk_tx_flash_motion_notify;
114 }
115
116 void gtk_tx_flash_mk_col(GtkTxFlash *tx_flash, GdkColor *col, float r, float g, float b)
117 {
118         float max=65535.0;
119         
120         col->red=(gint) (r*max);
121         col->green=(gint) (g*max);
122         col->blue=(gint) (b*max);
123         gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET(tx_flash)), col, 1, 1);           
124 }
125
126 static void
127 gtk_tx_flash_init (GtkTxFlash *tx_flash)
128 {
129         GdkColormap *priv;
130                         
131         priv=gdk_colormap_new(gtk_widget_get_visual(GTK_WIDGET(tx_flash)), 6);
132
133         gtk_widget_set_colormap(GTK_WIDGET(tx_flash), priv);
134
135         gtk_tx_flash_mk_col(tx_flash, &tx_flash->black, 0, 0, 0);
136         gtk_tx_flash_mk_col(tx_flash, &tx_flash->red, 1, 0.5, 0.5);
137         gtk_tx_flash_mk_col(tx_flash, &tx_flash->green, 0.5, 1, 0.5);   
138         gtk_tx_flash_mk_col(tx_flash, &tx_flash->lightgreen, 0, 0.7, 0);
139         gtk_tx_flash_mk_col(tx_flash, &tx_flash->redgreen, 0.7, 0, 0);
140 }
141
142 GtkWidget*
143 gtk_tx_flash_new ()
144 {
145   GtkTxFlash *tx_flash;
146
147   tx_flash = gtk_type_new (gtk_tx_flash_get_type ());
148
149   return GTK_WIDGET (tx_flash);
150 }
151
152 static void
153 gtk_tx_flash_destroy (GtkObject *object)
154 {
155   g_return_if_fail (object != NULL);
156   g_return_if_fail (GTK_IS_TX_FLASH (object));
157
158   if (GTK_OBJECT_CLASS (parent_class)->destroy)
159     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
160 }
161
162 static void
163 gtk_tx_flash_realize (GtkWidget *widget)
164 {
165   GtkTxFlash *tx_flash;
166   GdkWindowAttr attributes;
167   gint attributes_mask;
168
169   g_return_if_fail (widget != NULL);
170   g_return_if_fail (GTK_IS_TX_FLASH (widget));
171
172   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
173   tx_flash = GTK_TX_FLASH (widget);
174
175   attributes.x = widget->allocation.x;
176   attributes.y = widget->allocation.y;
177   attributes.width = widget->allocation.width;
178   attributes.height = widget->allocation.height;
179   attributes.wclass = GDK_INPUT_OUTPUT;
180   attributes.window_type = GDK_WINDOW_CHILD;
181   attributes.event_mask = gtk_widget_get_events (widget) | 
182     GDK_EXPOSURE_MASK;
183   attributes.visual = gtk_widget_get_visual (widget);
184   attributes.colormap = gtk_widget_get_colormap (widget);
185   
186   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
187
188   widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
189
190   widget->style = gtk_style_attach (widget->style, widget->window);
191
192   gdk_window_set_user_data (widget->window, widget);
193
194   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
195 }
196
197 static void 
198 gtk_tx_flash_size_request (GtkWidget *widget, GtkRequisition *requisition)
199 {
200         requisition->width = TX_FLASH_DEFAULT_SIZE_X;
201         requisition->height = TX_FLASH_DEFAULT_SIZE_Y;
202 }
203
204 static void
205 gtk_tx_flash_prepare (GtkWidget *widget)
206 {
207         GtkTxFlash *tx_flash;
208
209         g_return_if_fail (widget != NULL);
210         g_return_if_fail (GTK_IS_TX_FLASH (widget));
211         
212         tx_flash=GTK_TX_FLASH(widget);
213
214         tx_flash->levels=(widget->allocation.height-(2*DY))/DLEVEL;
215         tx_flash->last_level=0;
216         tx_flash->level_value=MAX_VALUE/(f_prec) tx_flash->levels;
217         tx_flash->red_level=(RED_BORDER/tx_flash->level_value);
218         
219         tx_flash->x1=DMINIX+S_MINIX+2;
220         tx_flash->x2=widget->allocation.width-tx_flash->x1-1;
221         tx_flash->max=0;
222 }
223
224 static void
225 gtk_tx_flash_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
226 {
227   GtkTxFlash *tx_flash;
228
229   g_return_if_fail (widget != NULL);
230   g_return_if_fail (GTK_IS_TX_FLASH (widget));
231   g_return_if_fail (allocation != NULL);
232
233   widget->allocation = *allocation;
234
235   gtk_tx_flash_prepare(widget);
236
237   if (GTK_WIDGET_REALIZED (widget))
238     {
239       tx_flash = GTK_TX_FLASH (widget);
240
241       gdk_window_move_resize (widget->window,
242                               allocation->x, allocation->y,
243                               allocation->width, allocation->height);
244
245     }
246 }
247
248 static void gtk_tx_flash_paint_yourself(GtkWidget *widget)
249 {
250   GtkTxFlash *tx_flash;
251   gint i, x11, x12,x21, x22, y;
252   int long_level;
253
254   tx_flash = GTK_TX_FLASH (widget);
255
256   gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->black);
257   
258   gdk_draw_rectangle(widget->window, widget->style->fg_gc[widget->state], 1, 0, 0, widget->allocation.width,widget->allocation.height); 
259
260   gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->lightgreen);
261
262   x12=DMINIX+S_MINIX;
263   x21=widget->allocation.width-1-x12;
264
265   for (i=0, y=widget->allocation.height-DY; i<=tx_flash->levels; y-=DLEVEL, i++)
266   {
267         if (i==0)
268         {
269                 long_level=1;
270         }
271         else if (i==tx_flash->red_level-1)
272         {
273                 long_level=1;
274         }
275         else if (i==tx_flash->red_level)
276         {
277                 long_level=1;
278                 gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->redgreen);
279         }
280         else if (i==tx_flash->levels)
281         {
282                 long_level=1;
283         }
284         else long_level=0;
285         
286         if (long_level)
287         {
288                 x11=x12-L_MINIX;
289                 x22=x21+L_MINIX;
290         }
291         else
292         {
293                 x11=x12-S_MINIX;
294                 x22=x21+S_MINIX;                
295         }
296         
297         gdk_draw_line(widget->window, widget->style->fg_gc[widget->state], x11, y, x12, y);
298         gdk_draw_line(widget->window, widget->style->fg_gc[widget->state], x21, y, x22, y);
299   }
300 }
301
302 static gint gtk_tx_flash_expose (GtkWidget *widget, GdkEventExpose *event)
303 {
304
305   g_return_val_if_fail (widget != NULL, FALSE);
306   g_return_val_if_fail (GTK_IS_TX_FLASH (widget), FALSE);
307   g_return_val_if_fail (event != NULL, FALSE);
308
309   if (event->count > 0)
310     return FALSE;
311
312   gtk_tx_flash_prepare(widget);
313   gtk_tx_flash_paint_yourself(widget);  
314
315   return FALSE;
316
317
318 void
319 gtk_tx_flash_set_level(GtkWidget *widget, f_prec new_value)
320 {
321   GtkTxFlash *tx_flash;
322   gint i, y;
323   int new_level;
324   int red=0;
325
326   g_return_if_fail (widget != NULL);
327   g_return_if_fail (GTK_IS_TX_FLASH (widget));
328
329   tx_flash = GTK_TX_FLASH (widget);
330
331   new_level=(int) (new_value/tx_flash->level_value);
332   
333   if (new_level>tx_flash->levels) new_level=tx_flash->levels;
334   
335 //  printf ("%f, %i, %i\n", tx_flash->level_value,new_level, tx_flash->last_level);
336   
337
338   if (new_level>tx_flash->max)
339   {
340         tx_flash->max=new_level;
341         tx_flash->max_cycles=MAX_MAX_CYCLES;
342   }
343   else
344   {
345         tx_flash->max_cycles--;
346   }
347   
348   if (tx_flash->max_cycles <= 0)
349   {     
350         y=widget->allocation.height-(DY+(tx_flash->max)*DLEVEL);
351         gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->black);
352         gdk_draw_line(widget->window, widget->style->fg_gc[widget->state], tx_flash->x1, y, tx_flash->x2, y);
353
354         if (tx_flash->max>0)
355         {
356                 tx_flash->max--;
357                 y+=DLEVEL;
358                 if (tx_flash->max>tx_flash->red_level)
359                 {
360                         gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->red);             
361                 }
362                 else
363                 {
364                         gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->green);           
365                 }
366                 gdk_draw_line(widget->window, widget->style->fg_gc[widget->state], tx_flash->x1, y, tx_flash->x2, y);   
367         }
368   }
369
370   if (new_level==tx_flash->last_level) return;
371
372   if (new_level<tx_flash->last_level) // make it look more realistic
373   {
374         new_level=tx_flash->last_level*globals.flash_response;
375   }
376   
377   if (new_level>tx_flash->last_level)
378   {
379           gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->green);
380   
381           for (i=tx_flash->last_level, y=widget->allocation.height-(DY+tx_flash->last_level*DLEVEL); i<=new_level; y-=DLEVEL, i++)
382           {
383                 if (!red)
384                 {
385                         if (i>=tx_flash->red_level)
386                         {
387                                 gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->red);
388                                 red=1;
389                         }
390                 }
391                 gdk_draw_line(widget->window, widget->style->fg_gc[widget->state], tx_flash->x1, y, tx_flash->x2, y);
392           }
393   }
394   else
395   {
396           gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx_flash->black);
397
398           if (tx_flash->last_level==tx_flash->max)
399           {
400                 i=tx_flash->last_level-1;
401           }
402           else
403           {
404                 i=tx_flash->last_level;
405           }
406
407           for (y=widget->allocation.height-(DY+i*DLEVEL); i>new_level; y+=DLEVEL, i--)
408           {
409                 gdk_draw_line(widget->window, widget->style->fg_gc[widget->state], tx_flash->x1, y, tx_flash->x2, y);
410           }
411   }
412   tx_flash->last_level=new_level;
413 }
414
415 void
416 gtk_tx_flash_clear (GtkWidget *widget)
417 {
418         GtkTxFlash *tx_flash;
419
420         tx_flash = GTK_TX_FLASH (widget);
421         
422         tx_flash->max=0;
423         tx_flash->max_cycles=0;
424         tx_flash->last_level=0;
425         
426         gtk_tx_flash_paint_yourself(widget);
427 }
428
429 #ifdef __cplusplus
430 }
431 #endif /* __cplusplus */