2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999-2002 Alexander König
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.
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.
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.
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.
31 #include <gtk/gtkwindow.h>
32 #include "tX_widget.h"
42 #endif /* __cplusplus */
44 #define TX_DEFAULT_SIZE_X 100
45 #define TX_DEFAULT_SIZE_Y 30
48 static void gtk_tx_class_init(GtkTxClass *);
49 static void gtk_tx_init(GtkTx * tx);
50 GtkWidget *gtk_tx_new(int16_t * wavdata, int wavsamples);
51 static void gtk_tx_destroy(GtkObject * object);
52 void gtk_tx_set_data(GtkTx * tx, int16_t * wavdata, int wavsamples);
53 static void gtk_tx_realize(GtkWidget * widget);
54 static void gtk_tx_size_request(GtkWidget * widget,
55 GtkRequisition * requisition);
56 static void gtk_tx_size_allocate(GtkWidget * widget,
57 GtkAllocation * allocation);
58 static gint gtk_tx_expose(GtkWidget * widget, GdkEventExpose * event);
59 static void gtk_tx_update(GtkTx * tx);
60 static void gtk_tx_prepare(GtkWidget * widget);
64 static GtkWidgetClass *parent_class = NULL;
66 guint gtk_tx_get_type() {
67 static guint tx_type = 0;
70 GtkTypeInfo tx_info = {
74 (GtkClassInitFunc) gtk_tx_class_init,
75 (GtkObjectInitFunc) gtk_tx_init,
81 tx_type = gtk_type_unique(gtk_widget_get_type(), &tx_info);
88 gtk_tx_class_init(GtkTxClass * gclass) {
89 GtkObjectClass *object_class;
90 GtkWidgetClass *widget_class;
92 object_class = (GtkObjectClass *) gclass;
93 widget_class = (GtkWidgetClass *) gclass;
95 parent_class = gtk_type_class(gtk_widget_get_type());
97 object_class->destroy = gtk_tx_destroy;
99 widget_class->realize = gtk_tx_realize;
100 widget_class->expose_event = gtk_tx_expose;
101 widget_class->size_request = gtk_tx_size_request;
102 widget_class->size_allocate = gtk_tx_size_allocate;
103 // widget_class->button_press_event = gtk_tx_button_press;
104 // widget_class->button_release_event = gtk_tx_button_release;
105 // widget_class->motion_notify_event = gtk_tx_motion_notify;
108 void gtk_tx_mk_col(GtkTx * tx, GdkColor * col, float r, float g,
112 col->red = (gint) (r * max);
113 col->green = (gint) (g * max);
114 col->blue = (gint) (b * max);
115 // printf("r: %8i, g: %8i, b: %8i\n", col->red, col->green, col->blue);
116 gdk_colormap_alloc_color(gtk_widget_get_colormap(GTK_WIDGET(tx)),
121 gtk_tx_init(GtkTx * tx) {
124 tx->disp_data = NULL;
129 tx->do_showframe = 0;
131 priv = gdk_colormap_new(gtk_widget_get_visual(GTK_WIDGET(tx)), 6);
132 gtk_widget_set_colormap(GTK_WIDGET(tx), priv);
134 gtk_tx_mk_col(tx, &tx->bg, 0, 0, 0);
136 gtk_tx_mk_col(tx, &tx->fg, 0, 1, 0);
138 gtk_tx_mk_col(tx, &tx->busy_fg, 1, 1, 1);
139 gtk_tx_mk_col(tx, &tx->busy_bg, 1, 0.4, 0.4);
141 gtk_tx_mk_col(tx, &tx->mute_fg, 0, 1, 1);
142 gtk_tx_mk_col(tx, &tx->mute_bg, 0, 0, 1);
143 gtk_tx_mk_col(tx, &tx->framecol, 1, 0, 0);
146 GtkWidget *gtk_tx_new(int16_t * wavdata, int wavsamples) {
149 tx = gtk_type_new(gtk_tx_get_type());
152 tx->samples = wavsamples;
154 // gtk_tx_prepare(GTK_WIDGET(tx));
156 return GTK_WIDGET(tx);
160 gtk_tx_destroy(GtkObject * object) {
161 g_return_if_fail(object != NULL);
162 g_return_if_fail(GTK_IS_TX(object));
164 if (GTK_OBJECT_CLASS(parent_class)->destroy)
165 (*GTK_OBJECT_CLASS(parent_class)->destroy) (object);
169 void gtk_tx_set_data(GtkTx * tx, int16_t * wavdata, int wavsamples) {
170 g_return_if_fail(tx != NULL);
171 g_return_if_fail(GTK_IS_TX(tx));
174 tx->samples = wavsamples;
176 gtk_tx_prepare(GTK_WIDGET(tx));
181 gtk_tx_realize(GtkWidget * widget) {
183 GdkWindowAttr attributes;
184 gint attributes_mask;
186 g_return_if_fail(widget != NULL);
187 g_return_if_fail(GTK_IS_TX(widget));
189 GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
192 attributes.x = widget->allocation.x;
193 attributes.y = widget->allocation.y;
194 attributes.width = widget->allocation.width;
195 attributes.height = widget->allocation.height;
196 attributes.wclass = GDK_INPUT_OUTPUT;
197 attributes.window_type = GDK_WINDOW_CHILD;
198 attributes.event_mask = gtk_widget_get_events(widget) |
200 attributes.visual = gtk_widget_get_visual(widget);
201 attributes.colormap = gtk_widget_get_colormap(widget);
204 GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
207 gdk_window_new(widget->parent->window, &attributes,
210 widget->style = gtk_style_attach(widget->style, widget->window);
212 gdk_window_set_user_data(widget->window, widget);
214 gtk_style_set_background(widget->style, widget->window,
219 gtk_tx_size_request(GtkWidget * widget, GtkRequisition * requisition) {
220 requisition->width = TX_DEFAULT_SIZE_X;
221 requisition->height = TX_DEFAULT_SIZE_Y;
225 gtk_tx_prepare(GtkWidget * widget) {
233 g_return_if_fail(widget != NULL);
234 g_return_if_fail(GTK_IS_TX(widget));
238 tx->spp = tx->samples / (widget->allocation.width - DBL_FR_SIZE);
239 tx->yc = widget->allocation.height / 2;
247 (int16_t *) malloc((widget->allocation.width - DBL_FR_SIZE)
251 for (x = 0, ptr = tx->disp_data;
252 x < widget->allocation.width - DBL_FR_SIZE;
254 value = tx->data[x * tx->spp];
255 for (sample = x * tx->spp; sample < (x + 1) * tx->spp;
257 value = (value + tx->data[sample]) / 2;
259 temp = ((f_prec) value) / 32767.0;
261 (int) (temp * (f_prec) (tx->yc - FR_SIZE));
265 tx->disp_data = NULL;
269 gtk_tx_size_allocate(GtkWidget * widget, GtkAllocation * allocation) {
272 g_return_if_fail(widget != NULL);
273 g_return_if_fail(GTK_IS_TX(widget));
274 g_return_if_fail(allocation != NULL);
276 widget->allocation = *allocation;
278 gtk_tx_prepare(widget);
280 if (GTK_WIDGET_REALIZED(widget)) {
283 gdk_window_move_resize(widget->window,
284 allocation->x, allocation->y,
285 allocation->width, allocation->height);
290 static gint gtk_tx_expose(GtkWidget * widget, GdkEventExpose * event) {
294 g_return_val_if_fail(widget != NULL, FALSE);
295 g_return_val_if_fail(GTK_IS_TX(widget), FALSE);
296 g_return_val_if_fail(event != NULL, FALSE);
298 if (event->count > 0)
303 gdk_gc_set_foreground(widget->style->fg_gc[widget->state],
306 gdk_draw_rectangle(widget->window,
307 widget->style->fg_gc[widget->state], 1, 0, 0,
308 widget->allocation.width,
309 widget->allocation.height);
311 gdk_gc_set_foreground(widget->style->fg_gc[widget->state],
315 for (x = FR_SIZE, pos = 0;
316 x < widget->allocation.width - FR_SIZE; x++, pos++) {
317 gdk_draw_line(widget->window,
318 widget->style->fg_gc[widget->state], x,
319 tx->yc - tx->disp_data[pos], x,
320 tx->yc + tx->disp_data[pos]);
323 gdk_draw_line(widget->window,
324 widget->style->fg_gc[widget->state],
327 widget->allocation.width - FR_SIZE, tx->yc);
330 gtk_tx_show_frame(tx, tx->do_showframe);
335 gtk_tx_update(GtkTx * tx) {
336 g_return_if_fail(tx != NULL);
337 g_return_if_fail(GTK_IS_TX(tx));
339 gtk_widget_draw(GTK_WIDGET(tx), NULL);
343 gtk_tx_prepare_pos_display(GtkTx * tx) {
348 gtk_tx_update_pos_display(GtkTx * tx, int sample, int mute) {
353 int current_x, x, y, yc, ymax;
355 /* Don't update if not required */
357 current_x = sample / tx->spp + FR_SIZE;
359 if ((current_x == tx->lastpos) && (tx->lastmute == mute))
363 /* speedup + easyness */
365 widget = GTK_WIDGET(tx);
366 window = widget->window;
368 if (current_x > widget->allocation.width - FR_SIZE - 2)
371 gc = widget->style->fg_gc[widget->state];
373 ymax = widget->allocation.height - FR_SIZE - 1;
375 /* Clean up last pos */
380 gdk_gc_set_foreground(gc, &tx->bg);
381 gdk_draw_line(window, gc, x, FR_SIZE, x, ymax);
383 gdk_gc_set_foreground(gc, &tx->fg);
384 y = tx->disp_data[x - FR_SIZE];
385 gdk_draw_line(window, gc, x, yc + y, x, yc - y);
387 /* store current_pos */
389 tx->lastpos = current_x;
391 /* draw current_pos */
396 gdk_gc_set_foreground(gc, &tx->mute_bg);
398 gdk_gc_set_foreground(gc, &tx->busy_bg);
400 gdk_draw_line(window, gc, x, FR_SIZE, x, ymax);
403 void gtk_tx_cleanup_pos_display(GtkTx * tx) {
409 widget = GTK_WIDGET(tx);
410 window = widget->window;
411 gc = widget->style->fg_gc[widget->state];
413 ymax = widget->allocation.height - FR_SIZE - 1;
418 gdk_gc_set_foreground(gc, &tx->bg);
419 gdk_draw_line(window, gc, x, FR_SIZE, x, ymax);
421 gdk_gc_set_foreground(gc, &tx->fg);
422 y = tx->disp_data[x - FR_SIZE];
423 gdk_draw_line(window, gc, x, yc + y, x, yc - y);
427 void gtk_tx_show_frame(GtkTx * tx, int show) {
433 widget = GTK_WIDGET(tx);
434 window = widget->window;
435 gc = widget->style->fg_gc[widget->state];
438 tx->do_showframe = show;
441 gdk_gc_set_foreground(gc, &tx->framecol);
443 gdk_gc_set_foreground(gc, &tx->bg);
446 for (i = 0; i < FR_SIZE; i++) {
447 gdk_draw_rectangle(window, gc, 0, i, i,
448 widget->allocation.width - (2 * i + 1),
449 widget->allocation.height - (2 * i + 1));
455 #endif /* __cplusplus */