]> lisas.de Git - terminatorX.git/blob - src/tX_widget.c
Uploaded Version 3.2 into ther repository... Alex
[terminatorX.git] / src / tX_widget.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_widget.c
20  
21     Description: This contains the implementation of the tx_widget.
22                  This file is based on the GTK+ widget example from
23                  the GTK+ 1.2 tutorial.
24 */    
25
26 #include <math.h>
27
28 #include <gtk/gtkwindow.h>
29 #include "tX_widget.h"
30 #include "tX_types.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 TX_DEFAULT_SIZE_X 200
42 #define TX_DEFAULT_SIZE_Y 100
43
44 /* pre dec */
45 static void gtk_tx_class_init (GtkTxClass *);
46 static void gtk_tx_init (GtkTx *tx);
47 GtkWidget* gtk_tx_new (int16_t *wavdata, int wavsamples);
48 static void gtk_tx_destroy (GtkObject *object);
49 void gtk_tx_set_data(GtkTx *tx, int16_t *wavdata, int wavsamples);
50 static void gtk_tx_realize (GtkWidget *widget);
51 static void gtk_tx_size_request (GtkWidget *widget, GtkRequisition *requisition);
52 static void gtk_tx_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
53 static gint gtk_tx_expose (GtkWidget *widget, GdkEventExpose *event);
54 static void gtk_tx_update (GtkTx *tx);
55 static void gtk_tx_prepare (GtkWidget *widget);
56
57 /* Local data */
58
59 static GtkWidgetClass *parent_class = NULL;
60
61 guint
62 gtk_tx_get_type ()
63 {
64   static guint tx_type = 0;
65
66   if (!tx_type)
67     {
68       GtkTypeInfo tx_info =
69       {
70         "GtkTx",
71         sizeof (GtkTx),
72         sizeof (GtkTxClass),
73         (GtkClassInitFunc) gtk_tx_class_init,
74         (GtkObjectInitFunc) gtk_tx_init,
75         (GtkArgSetFunc) NULL,
76         (GtkArgGetFunc) NULL,
77       };
78
79       tx_type = gtk_type_unique (gtk_widget_get_type (), &tx_info);
80     }
81
82   return tx_type;
83 }
84
85 static void
86 gtk_tx_class_init (GtkTxClass *gclass)
87 {
88   GtkObjectClass *object_class;
89   GtkWidgetClass *widget_class;
90
91   object_class = (GtkObjectClass*) gclass;
92   widget_class = (GtkWidgetClass*) gclass;
93
94   parent_class = gtk_type_class (gtk_widget_get_type ());
95
96   object_class->destroy = gtk_tx_destroy;
97
98   widget_class->realize = gtk_tx_realize;
99   widget_class->expose_event = gtk_tx_expose;
100   widget_class->size_request = gtk_tx_size_request;
101   widget_class->size_allocate = gtk_tx_size_allocate;
102 //  widget_class->button_press_event = gtk_tx_button_press;
103 //  widget_class->button_release_event = gtk_tx_button_release;
104 //  widget_class->motion_notify_event = gtk_tx_motion_notify;
105 }
106
107 void gtk_tx_mk_col(GtkTx *tx, GdkColor *col, float r, float g, float b)
108 {
109         float max=65535.0;
110         
111         col->red=(gint) (r*max);
112         col->green=(gint) (g*max);
113         col->blue=(gint) (b*max);
114 //      printf("r: %8i, g: %8i, b: %8i\n", col->red, col->green, col->blue);
115         gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET(tx)), col, 1, 1);         
116 }
117
118 static void
119 gtk_tx_init (GtkTx *tx)
120 {
121         GdkColormap *priv;
122                 
123         tx->disp_data=NULL;
124         
125         tx->data=NULL;
126         tx->samples=0;
127         
128         priv=gdk_colormap_new(gtk_widget_get_visual(GTK_WIDGET(tx)), 6);
129         gtk_widget_set_colormap(GTK_WIDGET(tx), priv);
130
131         gtk_tx_mk_col(tx, &tx->bg, 0, 0, 0);
132
133         gtk_tx_mk_col(tx, &tx->fg, 0, 1, 0);    
134
135         gtk_tx_mk_col(tx, &tx->busy_fg, 1, 1, 1);
136         gtk_tx_mk_col(tx, &tx->busy_bg, 1, 0.4, 0.4);
137
138         gtk_tx_mk_col(tx, &tx->mute_fg, 0, 1, 1);
139         gtk_tx_mk_col(tx, &tx->mute_bg, 0, 0, 1);       
140 }
141
142 GtkWidget*
143 gtk_tx_new (int16_t *wavdata, int wavsamples)
144 {
145   GtkTx *tx;
146
147   tx = gtk_type_new (gtk_tx_get_type ());
148
149   tx->data=wavdata;
150   tx->samples=wavsamples;
151
152 //  gtk_tx_prepare(GTK_WIDGET(tx));     
153
154   return GTK_WIDGET (tx);
155 }
156
157 static void
158 gtk_tx_destroy (GtkObject *object)
159 {
160   g_return_if_fail (object != NULL);
161   g_return_if_fail (GTK_IS_TX (object));
162
163   if (GTK_OBJECT_CLASS (parent_class)->destroy)
164     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
165 }
166
167
168 void gtk_tx_set_data(GtkTx *tx, int16_t *wavdata, int wavsamples)
169 {
170         g_return_if_fail (tx != NULL);
171         g_return_if_fail (GTK_IS_TX (tx));
172         
173         tx->data=wavdata;
174         tx->samples=wavsamples;
175         
176         gtk_tx_prepare(GTK_WIDGET(tx));         
177         gtk_tx_update(tx);
178 }
179
180 static void
181 gtk_tx_realize (GtkWidget *widget)
182 {
183   GtkTx *tx;
184   GdkWindowAttr attributes;
185   gint attributes_mask;
186
187   g_return_if_fail (widget != NULL);
188   g_return_if_fail (GTK_IS_TX (widget));
189
190   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
191   tx = GTK_TX (widget);
192
193   attributes.x = widget->allocation.x;
194   attributes.y = widget->allocation.y;
195   attributes.width = widget->allocation.width;
196   attributes.height = widget->allocation.height;
197   attributes.wclass = GDK_INPUT_OUTPUT;
198   attributes.window_type = GDK_WINDOW_CHILD;
199   attributes.event_mask = gtk_widget_get_events (widget) | 
200     GDK_EXPOSURE_MASK;
201   attributes.visual = gtk_widget_get_visual (widget);
202   attributes.colormap = gtk_widget_get_colormap (widget);
203   
204   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
205
206   widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
207
208   widget->style = gtk_style_attach (widget->style, widget->window);
209
210   gdk_window_set_user_data (widget->window, widget);
211
212   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
213 }
214
215 static void 
216 gtk_tx_size_request (GtkWidget *widget, GtkRequisition *requisition)
217 {
218         requisition->width = TX_DEFAULT_SIZE_X;
219         requisition->height = TX_DEFAULT_SIZE_Y;
220 }
221
222 static void
223 gtk_tx_prepare (GtkWidget *widget)
224 {
225         int x, sample;
226         f_prec temp;
227         int16_t *ptr;
228         int16_t value;
229                 
230         GtkTx *tx;
231
232         g_return_if_fail (widget != NULL);
233         g_return_if_fail (GTK_IS_TX (widget));
234         
235         tx=GTK_TX(widget);
236         
237         tx->spp=tx->samples/widget->allocation.width;
238         tx->yc=widget->allocation.height/2;
239         
240         if (tx->disp_data) free (tx->disp_data);
241         
242         if (tx->data)
243         {
244
245         tx->disp_data =(int16_t*) malloc(widget->allocation.width * sizeof(int16_t));
246
247         if (tx->disp_data)
248         for (x=0, ptr=tx->disp_data; x< widget->allocation.width; ptr++,x++)
249         {
250                 value=tx->data[x*tx->spp];
251                 for (sample=x*tx->spp; sample<(x+1)*tx->spp; sample++)
252                 {
253                         value=(value+tx->data[sample])/2;
254                 }
255                 temp=((f_prec) value)/32767.0;
256                 tx->disp_data[x]=(int) (temp * (f_prec) (tx->yc));
257         }
258         
259         }       
260         else tx->disp_data = NULL;
261         
262 }
263
264 static void
265 gtk_tx_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
266 {
267   GtkTx *tx;
268
269   g_return_if_fail (widget != NULL);
270   g_return_if_fail (GTK_IS_TX (widget));
271   g_return_if_fail (allocation != NULL);
272
273   widget->allocation = *allocation;
274
275   gtk_tx_prepare(widget);
276
277   if (GTK_WIDGET_REALIZED (widget))
278     {
279       tx = GTK_TX (widget);
280
281       gdk_window_move_resize (widget->window,
282                               allocation->x, allocation->y,
283                               allocation->width, allocation->height);
284
285     }
286 }
287
288 static gint gtk_tx_expose (GtkWidget *widget, GdkEventExpose *event)
289 {
290   GtkTx *tx;
291   gint x;
292
293   g_return_val_if_fail (widget != NULL, FALSE);
294   g_return_val_if_fail (GTK_IS_TX (widget), FALSE);
295   g_return_val_if_fail (event != NULL, FALSE);
296
297   if (event->count > 0)
298     return FALSE;
299   
300   tx = GTK_TX (widget);
301
302   gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx->bg);
303   
304   gdk_draw_rectangle(widget->window, widget->style->fg_gc[widget->state], 1, 0, 0, widget->allocation.width,widget->allocation.height); 
305
306   gdk_gc_set_foreground(widget->style->fg_gc[widget->state], &tx->fg);
307
308   if (tx->disp_data)
309   {
310         for (x=0; x< widget->allocation.width; x++)
311         {
312                 gdk_draw_line (widget->window,
313                      widget->style->fg_gc[widget->state],
314                      x,
315                      tx->yc-tx->disp_data[x],
316                      x,
317                      tx->yc+tx->disp_data[x]);
318         }       
319   }
320   else
321   {
322   gdk_draw_line (widget->window,
323                      widget->style->fg_gc[widget->state],
324                      0,
325                      tx->yc,
326                      widget->allocation.width,
327                      tx->yc);
328   }
329   return FALSE;
330 }
331
332 static void
333 gtk_tx_update (GtkTx *tx)
334 {
335   g_return_if_fail (tx != NULL);
336   g_return_if_fail (GTK_IS_TX (tx));
337
338   gtk_widget_draw (GTK_WIDGET(tx), NULL);
339 }
340
341 void
342 gtk_tx_prepare_pos_display(GtkTx *tx)
343 {
344         tx->lastpos=-1;
345 }
346
347 void
348 gtk_tx_update_pos_display(GtkTx *tx, int sample, int mute)
349 {
350         GtkWidget *widget;
351         GdkWindow *window;
352         GdkGC *gc;
353 //      GdkColor *fg;
354 //      GdkColor *bg;
355
356         int current_x, x, y, yc, ymax;
357
358         /* Don't update if not required */
359
360         current_x=sample/tx->spp;
361
362         if ((current_x==tx->lastpos) && (tx->lastmute==mute))return;
363         tx->lastmute=mute;
364
365         /* speedup + easyness */
366
367         widget = GTK_WIDGET(tx);
368         window = widget->window;
369         gc = widget->style->fg_gc[widget->state];
370         yc = tx->yc;
371         ymax=widget->allocation.height;
372         
373         /* Clean up last pos */
374         
375         x=tx->lastpos;
376
377         if (x>=0)
378         {       
379                 gdk_gc_set_foreground(gc, &tx->bg);
380                 gdk_draw_line(window, gc, x, 0, x, ymax);        
381         
382                 gdk_gc_set_foreground(gc, &tx->fg);
383                 y=tx->disp_data[x];
384                 gdk_draw_line(window, gc, x, yc+y, x, yc-y);            
385         }
386         /* store current_pos */
387                 
388         tx->lastpos=current_x;
389
390         /* draw current_pos */
391
392         x=current_x;
393
394         if (mute) gdk_gc_set_foreground(gc, &tx->mute_bg);
395         else gdk_gc_set_foreground(gc, &tx->busy_bg);
396         
397         gdk_draw_line(window, gc, x, 0, x, ymax);        
398
399         /* flush gdk buffer */  
400         
401         gdk_flush();
402 }
403
404 void gtk_tx_cleanup_pos_display(GtkTx *tx)
405 {
406         GtkWidget *widget;
407         GdkWindow *window;
408         GdkGC *gc;
409         int x, y, ymax, yc;
410
411         widget = GTK_WIDGET(tx);
412         window = widget->window;
413         gc = widget->style->fg_gc[widget->state];
414         yc = tx->yc;
415         ymax=widget->allocation.height;
416                                 
417         x=tx->lastpos;
418
419         if (x>=0)
420         {       
421                 gdk_gc_set_foreground(gc, &tx->bg);
422                 gdk_draw_line(window, gc, x, 0, x, ymax);        
423         
424                 gdk_gc_set_foreground(gc, &tx->fg);
425                 y=tx->disp_data[x];
426                 gdk_draw_line(window, gc, x, yc+y, x, yc-y);            
427         }
428         gdk_flush();    // moved to update() due to some gcc/egcs strangeness
429 }
430
431 #ifdef __cplusplus
432 }
433 #endif /* __cplusplus */