Loki Davison schrieb:
> On 5/2/07, audio-mobster <[EMAIL PROTECTED]> wrote:
>> Loki Davison schrieb:
>> > Phat is a collection of GTK+ widgets geared toward audio apps.
>> > Bug fixes and a few small feature updates. Most of the work done by
>> > Nedko! ;)
>> >
>> > We need help to implement all of Thorsten's new ideas. Check out
>> > http://thorwil.wordpress.com/ I'm really not able to do much coding at
>> > the moment due to RSI / overuse injury issues. I'm trying to keep away
>> >> from a computer.  There has been some discussion of making phat dual
>> > toolkit, gtk and qt4. Help with this would be very useful too. Contact
>> > me if you want to help and need svn access.
>> >
>> > Phat and pyphat can be download at http://phat.berlios.de/
>> >
>> > Cheers,
>> > Loki
>> > _______________________________________________
>> > Linux-audio-dev mailing list
>> > [email protected]
>> > http://lists.linuxaudio.org/mailman/listinfo.cgi/linux-audio-dev
>> >
>> Hi
>>
>> I already started implementing a SVG-Cairo version of a knob.
>> I'm playing with bounds and magnetic middle...
>>
>> Greets Uli
>> _______________________________________________
>> Linux-audio-dev mailing list
>> [email protected]
>> http://lists.linuxaudio.org/mailman/listinfo.cgi/linux-audio-dev
>>
> 
> put it in SVN, then everyone else can play with it too! Give me a yell
> for access.
> 
> Loki
> _______________________________________________
> Linux-audio-dev mailing list
> [email protected]
> http://lists.linuxaudio.org/mailman/listinfo.cgi/linux-audio-dev
> 

The sources are derived from cairo-clock:
http://cairographics.org/documentation
The tutorial by Davyd Madeley.

I added first support for scrolling, bounds and magnetic.
See drawing function phat_svg_knob_face_scroll() and
emit_scroll_event_signal().
The button is still upside down.
No shading or translucency yet, I got no compositmanager running.
all: test_widget

test_widget: test_widget.c phatsvgknob.c phatsvgknob.h 
phatsvgknob-marshallers.c phatsvgknob-marshallers.h
        gcc -g -o test_widget test_widget.c phatsvgknob.c 
phatsvgknob-marshallers.c \
                `pkg-config --libs --cflags gtk+-2.0`

phatsvgknob-marshallers.c: phatsvgknob-marshallers.list
        glib-genmarshal --prefix _phatsvgknob_marshal --body $< > $@

phatsvgknob-marshallers.h: phatsvgknob-marshallers.list
        glib-genmarshal --prefix _phatsvgknob_marshal --header $< > $@

clean:  
        -rm -rf test_widget Binaries/test_widget
/*
 * phatsvgknob.c
 *
 * A GTK+ widget that implements a knob face
 *
 * (C) 2007, Ulrich Lorenz Schlueter
 * 
 * derived from:
 * 	 http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28
 *   http://gnomejournal.org/article/36/writing-a-widget-using-cairo-and-gtk28-part-2
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *	
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Authors:
 *   Ulrich Lorenz Schlueter  <[EMAIL PROTECTED]>
 */

#include <gtk/gtk.h>
#include <math.h>
#include <time.h>

#include "phatsvgknob.h"
#include "phatsvgknob-marshallers.h"

#define PHAT_SVG_KNOB_FACE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PHAT_TYPE_SVG_KNOB_FACE, PhatSvgKnobFacePrivate))

G_DEFINE_TYPE (PhatSvgKnobFace, phat_svg_knob_face, GTK_TYPE_DRAWING_AREA);

static gboolean phat_svg_knob_face_expose (GtkWidget *knob, GdkEventExpose *event);
static gboolean phat_svg_knob_face_button_press (GtkWidget *knob, GdkEventButton *event);
static gboolean phat_svg_knob_face_button_release (GtkWidget *knob, GdkEventButton *event);
static gboolean phat_svg_knob_face_motion_notify (GtkWidget *knob, GdkEventMotion *event);
static gboolean phat_svg_knob_face_scroll (GtkWidget *knob, GdkEventScroll *event);
static gboolean phat_svg_knob_face_update (gpointer data);

typedef struct _PhatSvgKnobFacePrivate PhatSvgKnobFacePrivate;

struct _PhatSvgKnobFacePrivate
{
	double decibel; 		/* the decibels */
	double decibel_offset;  /* the offset of the decibels */

	gboolean dragging;      /* true if the interface is being dragged */
};

enum
{
	VALUE_CHANGED,
	LAST_SIGNAL,
};

static guint phat_svg_knob_face_signals[LAST_SIGNAL] = { 0 };

static void
phat_svg_knob_face_class_init (PhatSvgKnobFaceClass *class)
{
	GObjectClass *obj_class;
	GtkWidgetClass *widget_class;

	obj_class = G_OBJECT_CLASS (class);
	widget_class = GTK_WIDGET_CLASS (class);

	/* GtkWidget signals */
	widget_class->expose_event = phat_svg_knob_face_expose;
	widget_class->button_press_event = phat_svg_knob_face_button_press;
	widget_class->button_release_event = phat_svg_knob_face_button_release;
	widget_class->motion_notify_event = phat_svg_knob_face_motion_notify;
	widget_class->scroll_event = phat_svg_knob_face_scroll;

	/* PhatSvgKnobFace signals */
	phat_svg_knob_face_signals[VALUE_CHANGED] = g_signal_new (
			"value-changed",
			G_OBJECT_CLASS_TYPE (obj_class),
			G_SIGNAL_RUN_FIRST,
			G_STRUCT_OFFSET (PhatSvgKnobFaceClass, value_changed),
			NULL, NULL,
			_phatsvgknob_marshal_VOID__INT_INT,
			G_TYPE_NONE, 2,
			G_TYPE_INT,
			G_TYPE_INT);

	g_type_class_add_private (obj_class, sizeof (PhatSvgKnobFacePrivate));
}

static void
phat_svg_knob_face_init (PhatSvgKnobFace *knob)
{
	gtk_widget_add_events (GTK_WIDGET (knob),
			GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
			GDK_SCROLL_MASK |GDK_POINTER_MOTION_MASK);

	phat_svg_knob_face_update (knob);
}

static void
draw (GtkWidget *knob, cairo_t *cr)
{
	PhatSvgKnobFacePrivate *priv;
	double x, y;
	double radius;
	int i;
	double decibels;
	
	priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);

	x = knob->allocation.width / 2;
	y = knob->allocation.height / 2;
	radius = MIN (knob->allocation.width / 2,
		      knob->allocation.height / 2) - 10;

	/* knob back */
	cairo_arc (cr, x, y, radius, 0, 2 * M_PI);
	cairo_set_source_rgb (cr, 0, 0, 0);
	cairo_fill_preserve(cr);

	cairo_set_source_rgb (cr, 1, 0.5, 0);
	cairo_stroke (cr);
	cairo_save (cr);

	/* knob ticks */
	for (i = 6; i < 25; i++)
	{
		int inset;
	
		cairo_save (cr); /* stack-pen-size */
		
		if ( i %  3 == 0 )
		{
			inset = 0.075 * radius;
			cairo_set_line_width (cr, 1.5 * cairo_get_line_width (cr));
		} else {
			inset = 0.05 * radius;
			cairo_set_line_width (cr, 1 * cairo_get_line_width (cr));
		}
		
		cairo_move_to (cr,
				x + (radius + inset) * cos (i * M_PI / 10),
				y + (radius + inset) * sin (i * M_PI / 10));
		cairo_line_to (cr,
				x + radius * cos (i * M_PI / 10),
				y + radius * sin (i * M_PI / 10));
		cairo_stroke (cr);
		cairo_restore (cr); /* stack-pen-size */
	}

	/* knob hands */
	decibels = priv->decibel + priv->decibel_offset;
	/* decibel hand:
	 * the decibel hand is rotated 6 degrees (pi/45 r) per decibel
	 */
	cairo_move_to (cr, x, y);
	cairo_set_line_width (cr, 2.3 * cairo_get_line_width (cr));
	cairo_line_to (cr, x + radius  * sin (M_PI / PHAT_SVG_KNOB_DEFAULT_ADJUST * decibels),
			   y + radius  * -cos (M_PI / PHAT_SVG_KNOB_DEFAULT_ADJUST * decibels));
	
	cairo_stroke (cr);
	cairo_restore (cr);
}

static gboolean
phat_svg_knob_face_expose (GtkWidget *knob, GdkEventExpose *event)
{
	cairo_t *cr;

	/* get a cairo_t */
	cr = gdk_cairo_create(knob->window);

	cairo_rectangle (cr,
			event->area.x, event->area.y,
			event->area.width, event->area.height);
			
	cairo_clip (cr);
	
	draw (knob, cr);

	cairo_destroy (cr);

	return FALSE;
}

static gboolean
phat_svg_knob_face_button_press (GtkWidget *knob, GdkEventButton *event)
{
	PhatSvgKnobFacePrivate *priv;
	double decibels;
	double lx, ly;
	double px, py;
	double u, d2;
	
	priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);

	decibels = priv->decibel + priv->decibel_offset;

	/* From
	 * http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
	 */
	px = event->x - knob->allocation.width / 2;
	py = knob->allocation.height / 2 - event->y;
	lx = sin (M_PI / PHAT_SVG_KNOB_DEFAULT_ADJUST * decibels); ly = cos (M_PI / PHAT_SVG_KNOB_DEFAULT_ADJUST * decibels);
	u = lx * px + ly * py;

	/* on opposite side of origin */
	if (u < 0) return FALSE;

	d2 = pow (px - u * lx, 2) + pow (py - u * ly, 2);

	if (d2 < 25) /* 5 pixels away from the line */
	{
		priv->dragging = TRUE;
	}
	
	return FALSE;
}

static void
phat_svg_knob_face_redraw_canvas (PhatSvgKnobFace *knob)
{
	GtkWidget *widget;
	GdkRegion *region;
	
	widget = GTK_WIDGET (knob);

	if (!widget->window) return;

	region = gdk_drawable_get_clip_region (widget->window);
	/* redraw the cairo canvas completely by exposing it */
	gdk_window_invalidate_region (widget->window, region, TRUE);
	gdk_window_process_updates (widget->window, TRUE);

	gdk_region_destroy (region);
}

static emit_value_changed_signal (PhatSvgKnobFace *knob, int x, int y)
{
	PhatSvgKnobFacePrivate *priv;
	double phi;
	double decibels;
	
	priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);
	
	/* decode the decibel hand */
	/* normalise the coordinates around the origin */
	x -= GTK_WIDGET (knob)->allocation.width / 2;
	y -= GTK_WIDGET (knob)->allocation.height / 2;

	/* phi is a bearing from north clockwise, use the same geometry as we
	 * did to position the decibel hand originally */
	phi = atan2 (x, -y);
	if (phi < 0)
		phi += M_PI * 2;

	decibels = phi * PHAT_SVG_KNOB_DEFAULT_ADJUST / M_PI;
	
	if(decibels<=5){
		/* Stop drawing on min */
		priv->decibel=5;
		priv->decibel_offset = 0;
		decibels=5;
	} else if(decibels>=85){
		/* Stop drawing on max */
		priv->decibel=85;
		priv->decibel_offset = 0;
		decibels=85;
	} else if(decibels>=43 && decibels<=47){
		/* Magnetic on 45 */
		priv->decibel=45;
		priv->decibel_offset = 0;
		decibels=45;
	} else {
		/* update the offset */
		priv->decibel_offset = decibels - priv->decibel;
		priv->decibel= decibels;
	}

	phat_svg_knob_face_redraw_canvas (knob);
	
	g_signal_emit (knob,
			phat_svg_knob_face_signals[VALUE_CHANGED],
			0, decibels);
}

static emit_scroll_event_signal (PhatSvgKnobFace *knob, int direction)
{
	PhatSvgKnobFacePrivate *priv;
	
	priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);
	
	if(direction==0){
		priv->decibel = priv->decibel + 1;
	} else if(direction==1){
		priv->decibel = priv->decibel -1;
	} else if(direction==2){
		priv->decibel = priv->decibel + 5;
	} else {
		priv->decibel = priv->decibel -5;
	}
	
	/* Stop drawing on min */
	if(priv->decibel<=5){
		priv->decibel=5;
	}
	/* Stop drawing on max */
	if (priv->decibel>=85){
		priv->decibel=85;
	}
	 
	phat_svg_knob_face_redraw_canvas(knob);

	g_signal_emit (knob,
			phat_svg_knob_face_signals[VALUE_CHANGED],
			0, priv->decibel);
}

static gboolean
phat_svg_knob_face_scroll (GtkWidget *knob, GdkEventScroll *event)
{
	emit_scroll_event_signal (PHAT_SVG_KNOB_FACE (knob),
				event->direction);
				
	return FALSE;
}

static gboolean
phat_svg_knob_face_motion_notify (GtkWidget *knob, GdkEventMotion *event)
{
	PhatSvgKnobFacePrivate *priv;
	int x, y;

	priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);

	if (priv->dragging)
	{
		emit_value_changed_signal (PHAT_SVG_KNOB_FACE (knob),
				event->x, event->y);
	}
	return FALSE;
}

static gboolean
phat_svg_knob_face_button_release (GtkWidget *knob, GdkEventButton *event)
{
	PhatSvgKnobFacePrivate *priv;

	priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);
	
	if (priv->dragging)
	{
		priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);
		priv->dragging = FALSE;
		emit_value_changed_signal (PHAT_SVG_KNOB_FACE (knob),
				event->x, event->y);
	}

	return FALSE;
}

static gboolean
phat_svg_knob_face_update (gpointer data)
{
	PhatSvgKnobFace *knob;
	PhatSvgKnobFacePrivate *priv;

	knob = PHAT_SVG_KNOB_FACE (data);
	priv = PHAT_SVG_KNOB_FACE_GET_PRIVATE (knob);
	
	phat_svg_knob_face_redraw_canvas (knob);

	return TRUE; /* keep running this event */
}

GtkWidget *
phat_svg_knob_face_new (void)
{
	return g_object_new (PHAT_TYPE_SVG_KNOB_FACE, NULL);
}
/*
 * phatsvgknob.h
 *
 * A GTK+ widget that implements a knob face
 *
 * (C) 2007, Ulrich Lorenz Schlueter
 * 
 * derived from:
 * 	 http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28
 *   http://gnomejournal.org/article/36/writing-a-widget-using-cairo-and-gtk28-part-2
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *	
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Authors:
 *   Ulrich Lorenz Schlueter  <[EMAIL PROTECTED]>
 */

#ifndef __PHAT_SVG_KNOB_FACE_H__
#define __PHAT_SVG_KNOB_FACE_H__

#include <gtk/gtk.h>

G_BEGIN_DECLS

#define PHAT_TYPE_SVG_KNOB_FACE		(phat_svg_knob_face_get_type ())
#define PHAT_SVG_KNOB_FACE(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), PHAT_TYPE_SVG_KNOB_FACE, PhatSvgKnobFace))
#define PHAT_SVG_KNOB_FACE_CLASS(obj)	(G_TYPE_CHECK_CLASS_CAST ((obj), PHAT_SVG_KNOB_FACE, PhatSvgKnobFaceClass))
#define PHAT_IS_SVG_KNOB_FACE(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), PHAT_TYPE_SVG_KNOB_FACE))
#define PHAT_IS_SVG_KNOB_FACE_CLASS(obj)	(G_TYPE_CHECK_CLASS_TYPE ((obj), PHAT_TYPE_SVG_KNOB_FACE))
#define PHAT_SVG_KNOB_FACE_GET_CLASS	(G_TYPE_INSTANCE_GET_CLASS ((obj), PHAT_TYPE_SVG_KNOB_FACE, PhatSvgKnobFaceClass))

#define PHAT_SVG_KNOB_DEFAULT_ADJUST (45)

typedef struct _PhatSvgKnobFace		PhatSvgKnobFace;
typedef struct _PhatSvgKnobFaceClass	PhatSvgKnobFaceClass;

struct _PhatSvgKnobFace
{
	GtkDrawingArea parent;

	/* < private > */
};

struct _PhatSvgKnobFaceClass
{
	GtkDrawingAreaClass parent_class;

	void	(* value_changed)	(PhatSvgKnobFace *knob, double decibel);
};

GtkWidget *phat_svg_knob_face_new (void);

G_END_DECLS

#endif
#include	<glib-object.h>


#ifdef G_ENABLE_DEBUG
#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
#define g_marshal_value_peek_char(v)     g_value_get_char (v)
#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
#define g_marshal_value_peek_int(v)      g_value_get_int (v)
#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
#define g_marshal_value_peek_long(v)     g_value_get_long (v)
#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
#define g_marshal_value_peek_float(v)    g_value_get_float (v)
#define g_marshal_value_peek_double(v)   g_value_get_double (v)
#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v)    g_value_get_param (v)
#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
#define g_marshal_value_peek_object(v)   g_value_get_object (v)
#else /* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
 *          Do not access GValues directly in your code. Instead, use the
 *          g_value_get_*() functions
 */
#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
#endif /* !G_ENABLE_DEBUG */


/* VOID:INT,INT (phatsvgknob-marshallers.list:2) */
void
_phatsvgknob_marshal_VOID__INT_INT (GClosure     *closure,
                              GValue       *return_value,
                              guint         n_param_values,
                              const GValue *param_values,
                              gpointer      invocation_hint,
                              gpointer      marshal_data)
{
  typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer     data1,
                                              gint         arg_1,
                                              gint         arg_2,
                                              gpointer     data2);
  register GMarshalFunc_VOID__INT_INT callback;
  register GCClosure *cc = (GCClosure*) closure;
  register gpointer data1, data2;

  g_return_if_fail (n_param_values == 3);

  if (G_CCLOSURE_SWAP_DATA (closure))
    {
      data1 = closure->data;
      data2 = g_value_peek_pointer (param_values + 0);
    }
  else
    {
      data1 = g_value_peek_pointer (param_values + 0);
      data2 = closure->data;
    }
  callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);

  callback (data1,
            g_marshal_value_peek_int (param_values + 1),
            g_marshal_value_peek_int (param_values + 2),
            data2);
}

#ifndef ___phatsvgknob_marshal_MARSHAL_H__
#define ___phatsvgknob_marshal_MARSHAL_H__

#include	<glib-object.h>

G_BEGIN_DECLS

/* VOID:INT,INT (phatsvgknob-marshallers.list:2) */
extern void _phatsvgknob_marshal_VOID__INT_INT (GClosure     *closure,
                                          GValue       *return_value,
                                          guint         n_param_values,
                                          const GValue *param_values,
                                          gpointer      invocation_hint,
                                          gpointer      marshal_data);

G_END_DECLS

#endif /* ___phatsvgknob_marshal_MARSHAL_H__ */

# these marshallers are generated with glib-genmarshal(1)
VOID:INT,INT
/*
 * main.c
 *
 * Test widget
 *
 * (C) 2007, Ulrich Lorenz Schlueter
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *	
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Authors:
 *   Ulrich Lorenz Schlueter  <[EMAIL PROTECTED]>
 */

#include <gtk/gtk.h>

#include "phatsvgknob.h"

static void
value_changed_cb (PhatSvgKnobFace *knob, double decibel, gpointer data)
{
	g_print ("value-changed - %02f\n", decibel);
}

int
main (int argc, char **argv)
{
	GtkWidget *window;
	GtkWidget *knob;

	gtk_init (&argc, &argv);

	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	
	knob = phat_svg_knob_face_new ();
	
	gtk_widget_set_size_request (knob, 100, 100);
	
	gtk_container_add (GTK_CONTAINER (window), knob);

	g_signal_connect (window, "destroy",
			G_CALLBACK (gtk_main_quit), NULL);

	g_signal_connect (knob, "value-changed",
			G_CALLBACK (value_changed_cb), NULL);
	
	gtk_widget_show_all (window);

	gtk_main ();
}
_______________________________________________
Linux-audio-dev mailing list
[email protected]
http://lists.linuxaudio.org/mailman/listinfo.cgi/linux-audio-dev

Reply via email to