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