Mercurial > hg > dmlib
changeset 344:9cf1a58b0234
Beginnings of the editor.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 15 Oct 2012 22:48:41 +0300 |
parents | 6ecc7eb6d158 |
children | cac13f180169 |
files | Makefile Makefile.gen config.mak.in dmeditor.c gtktimeline.c gtktimeline.h gtkwaveform.c gtkwaveform.h |
diffstat | 8 files changed, 842 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Mon Oct 15 21:27:24 2012 +0300 +++ b/Makefile Mon Oct 15 22:48:41 2012 +0300 @@ -5,6 +5,8 @@ SDL_LDFLAGS=`sdl-config --static-libs` TREMOR_CFLAGS=-I/usr/local/lib/ TREMOR_LDFLAGS=/usr/local/lib/libvorbisidec.a /usr/lib/i386-linux-gnu/libogg.a +GTK_CFLAGS=`pkg-config --cflags gtk+-2.0 glib-2.0 cairo` +GTK_LDFLAGS=`pkg-config --libs gtk+-2.0 glib-2.0 cairo` RANLIB=ranlib
--- a/Makefile.gen Mon Oct 15 21:27:24 2012 +0300 +++ b/Makefile.gen Mon Oct 15 22:48:41 2012 +0300 @@ -11,6 +11,19 @@ DM_CFLAGS += -I$(DMLIB) endif + +### +### Editor +### +ifeq ($(DM_BUILD_EDITOR),yes) +ifneq ($(DEMO_BIN),) +BINARIES += ed_$(DEMO_BIN) +endif +endif + +EDITOR_OBJS = gtktimeline.o gtkwaveform.o dmeditor.o + + ### ### Form additional compilation defines based on settings ### @@ -212,8 +225,7 @@ DMLIB_A=$(OBJPATH)dmlib.a DMLIB_OBJS += dmfile.o dmlib.o dmlerp.o dmstring.o \ dmargs.o dmvecmat.o dmperlin.o dmimage.o \ - dmwav.o dmengine.o dmsimple.o \ - dmtimeline.o dmtimelinew.o dmq3d.o + dmwav.o dmengine.o dmtimeline.o dmtimelinew.o dmq3d.o ifeq ($(DM_BUILD_TESTS),yes) BINARIES += vecmattest fptest @@ -226,6 +238,11 @@ ### ### Generic rules ### +$(OBJPATH)gtk%.o: $(DMLIB)gtk%.c $(DMLIB)gtk%.h + @echo " CC $+" + @$(CC) $(CFLAGS) -c -o $@ $< $(DM_CFLAGS) $(GTK_CFLAGS) + + $(OBJPATH)%.d: $(DMLIB)%.c @echo > $@ @grep '#\s*include\s*\"' $< | sed 's/#\s*include\s\s*"\(.*\)"/\1/' | while read i; do if test -e "$$i"; then echo "$$i" >> $@; fi; done @@ -294,10 +311,6 @@ ### ### Tests and binaries ### -$(BINPATH)%$(EXEEXT): $(OBJPATH)%.o $(DMLIB_A) - @echo " LINK $+" - @$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(SDL_LDFLAGS) - $(BINPATH)vview$(EXEEXT): $(OBJPATH)vview.o $(DMLIB_A) @echo " LINK $+" @$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(SDL_LDFLAGS) -lSDL_ttf @@ -350,6 +363,18 @@ @echo " LINK $+" @$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(SDL_LDFLAGS) +### +### Editor targets +### +$(OBJPATH)dmeditor.o: $(DMLIB)dmeditor.c + @echo " CC $+" + @$(CC) $(CFLAGS) -c -o $@ $< $(DM_CFLAGS) $(GTK_CFLAGS) + + +$(BINPATH)ed_$(DEMO_BIN)$(EXEEXT): $(OBJPATH)$(DEMO_BIN).o $(addprefix $(OBJPATH),$(EDITOR_OBJS)) $(addprefix $(OBJPATH),$(DEMO_OBJS)) $(DMLIB_A) + @echo " LINK $+" + @$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(SDL_LDFLAGS) $(GTK_LDFLAGS) + ### ### Special targets
--- a/config.mak.in Mon Oct 15 21:27:24 2012 +0300 +++ b/config.mak.in Mon Oct 15 22:48:41 2012 +0300 @@ -1,10 +1,10 @@ # Build engine tests and tools? (Please notice that what # actually gets built it also affected by other options) -DM_BUILD_TESTS=no +DM_BUILD_TESTS=yes DM_BUILD_TOOLS=yes -# Enable OpenGL specifics (does not mean that OpenGL is automatically used, tho) -DM_USE_OPENGL=no +# Build Gtk+2 based demo editor? +DM_BUILD_EDITOR=yes # Build with runtime asserts? DM_USE_ASSERTS=yes @@ -41,7 +41,7 @@ JSS_LIGHT=no # Build with extra debugging code? (disabled by JSS_LIGHT=yes) -JSS_DEBUG=yes +JSS_DEBUG=no ### Support loading of XM-format module files @@ -74,3 +74,4 @@ ### Locking/thread support ### JSS_SUP_THREADS=yes +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmeditor.c Mon Oct 15 22:48:41 2012 +0300 @@ -0,0 +1,283 @@ +#include <SDL.h> +#include "dmengine.h" +#include "gtktimeline.h" +#include "gtkwaveform.h" + + +static void set_value(GtkWidget * widget, gpointer data) +{ + GdkRegion *region; + + GtkRange *range = (GtkRange *) widget; + GtkTimeline *timeline = (GtkTimeline *) data; + + gint offs = gtk_range_get_value(range); + + gtk_timeline_set_offs(timeline, offs * 1000); +/* + region = gdk_drawable_get_clip_region(timeline->window); + gdk_window_invalidate_region(timeline->window, region, TRUE); + gdk_window_process_updates(timeline->window, TRUE); +*/ +} + + +static void engineAudioCallback(void *userdata, Uint8 * stream, int len) +{ + (void) userdata; + + if (engine.paused) + { + memset(stream, 0, len); + } + else +#ifdef DM_USE_JSS + { + if (engine.dev != NULL) + jvmRenderAudio(engine.dev, stream, + len / jvmGetSampleSize(engine.dev)); + } +#endif +#ifdef DM_USE_TREMOR + if (engine.audioPos + len >= engine.audio->rdataSize) + { + engine.exitFlag = TRUE; + } + else + { + memcpy(stream, engine.audio->rdata + engine.audioPos, len); + engine.audioPos += len; + } +#endif +} + + +int engineOpenResources() +{ + int err; + + if ((err = + dmres_init(engine.optPackFilename, engine.optDataPath, + engine.optResFlags, engineClassifier)) != DMERR_OK) + dmError("Could not initialize resource manager: %d, %s.\n", err, + dmErrorStr(err)); + return err; +} + + +int engineLoadResources() +{ + int err, loaded, total; + err = dmres_preload(TRUE, &loaded, &total); + + while ((err = dmres_preload(FALSE, &loaded, &total)) == DMERR_PROGRESS) + { + // Show a nice progress bar while loading + if (total > 0 && (loaded % 2) == 0) + { +/* + if ((err = engineShowProgress(loaded, total)) != DMERR_OK) + return err; +*/ + } + } +} + +int engineReloadResources() +{ + int err; + + dmres_close(); + if ((err = engineOpenResources()) != DMERR_OK) + return err; + if ((err = engineLoadResources()) != DMERR_OK) + return err; + + return DMERR_OK; +} + + +BOOL engineInitializeVideo() +{ + return TRUE; +} + + +int main(int argc, char **argv) +{ + int err; + BOOL initSDL = FALSE; + + memset(&frame, 0, sizeof(frame)); + memset(&engine, 0, sizeof(engine)); + + // Pre-initialization + if ((err = demoPreInit()) != DMERR_OK) + goto error_exit; + + gtk_init(&argc, &argv); + + // Initialize resource subsystem + dmPrint(1, "Initializing resources subsystem.\n"); + if ((err = engineOpenResources()) != DMERR_OK) + goto error_exit; + + // Initialize SDL components + dmPrint(1, "Initializing libSDL.\n"); + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) + { + dmError("Could not initialize SDL: %s\n", SDL_GetError()); + goto error_exit; + } + initSDL = TRUE; + + // Initialize audio parts + if (engine.optAfmt.freq == 0 && engine.optAfmt.channels == 0) + { + // Defaults, if none seem to be set + engine.optAfmt.freq = 44100; + engine.optAfmt.format = AUDIO_S16SYS; + engine.optAfmt.channels = 2; + engine.optAfmt.samples = engine.optAfmt.freq / 16; + } + +#ifdef DM_USE_JSS + jssInit(); + + switch (engine.optAfmt.format) + { + case AUDIO_S16SYS: + engine.jss_format = JSS_AUDIO_S16; + break; + case AUDIO_U16SYS: + engine.jss_format = JSS_AUDIO_U16; + break; + case AUDIO_S8: + engine.jss_format = JSS_AUDIO_S8; + break; + case AUDIO_U8: + engine.jss_format = JSS_AUDIO_U8; + break; + } + + dmPrint(1, "Initializing miniJSS mixer with fmt=%d, chn=%d, freq=%d\n", + engine.jss_format, engine.optAfmt.channels, engine.optAfmt.freq); + + if ((engine.dev = + jvmInit(engine.jss_format, engine.optAfmt.channels, + engine.optAfmt.freq, JMIX_AUTO)) == NULL) + { + dmError("jvmInit() returned NULL, voi perkele.\n"); + goto error_exit; + } + + if ((engine.plr = jmpInit(engine.dev)) == NULL) + { + dmError("jmpInit() returned NULL\n"); + goto error_exit; + } +#endif + + // Initialize SDL audio + dmPrint(1, "Trying to init SDL audio with: fmt=%d, chn=%d, freq=%d\n", + engine.optAfmt.format, engine.optAfmt.channels, + engine.optAfmt.freq); + + engine.optAfmt.callback = engineAudioCallback; + + if (SDL_OpenAudio(&engine.optAfmt, NULL) < 0) + { + dmError("Couldn't open SDL audio: %s\n", SDL_GetError()); + goto error_exit; + } + + // Initialize SDL video + if (engine.demoInitPreVideo != NULL && + (err = engine.demoInitPreVideo()) != DMERR_OK) + { + dmError("demoInitPreVideo() failed, %d: %s\n", err, dmErrorStr(err)); + goto error_exit; + } + + if (!engineInitializeVideo()) + goto error_exit; + + if (engine.demoInitPostVideo != NULL && + (err = engine.demoInitPostVideo()) != DMERR_OK) + { + dmError("demoInitPostVideo() failed, %d: %s\n", err, dmErrorStr(err)); + goto error_exit; + } + + // Load resources + dmPrint(1, "Loading resources, please wait...\n"); + if ((err = engineLoadResources()) != DMERR_OK) + { + dmError("Error loading resources, %d: %s.\n", err, dmErrorStr(err)); + goto error_exit; + } + + // Final initializations + if ((err = engine.demoInit()) != DMERR_OK) + goto error_exit; + + + // Initialize GUI + GtkWidget *window; + GtkWidget *timeline; + GtkWidget *fixed; + GtkWidget *scale; + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "TIMELINE widget"); + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_window_set_default_size(GTK_WINDOW(window), 200, 180); + g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); + fixed = gtk_fixed_new(); + gtk_container_add(GTK_CONTAINER(window), fixed); + timeline = gtk_timeline_new(); + gtk_fixed_put(GTK_FIXED(fixed), timeline, 30, 40); + scale = gtk_vscale_new_with_range(0.0, 100.0, 1.0); + gtk_range_set_inverted(GTK_RANGE(scale), TRUE); + gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP); + gtk_widget_set_size_request(scale, 50, 120); + gtk_fixed_put(GTK_FIXED(fixed), scale, 130, 20); + g_signal_connect(G_OBJECT(scale), "value_changed", G_CALLBACK(set_value),(gpointer) timeline); + + gtk_widget_show(timeline); + gtk_widget_show(fixed); + gtk_widget_show_all(window); + + gtk_main(); + + +error_exit: + + dmPrint(1, "Shutting down.\n"); + SDL_ShowCursor(SDL_ENABLE); + + if (engine.screen) + SDL_FreeSurface(engine.screen); + + SDL_LockAudio(); + SDL_PauseAudio(1); +#ifdef DM_USE_JSS + jmpClose(engine.plr); + jvmClose(engine.dev); + jssClose(); +#endif + SDL_UnlockAudio(); + + dmres_close(); + + if (engine.demoShutdown != NULL) + engine.demoShutdown(); + + if (initSDL) + SDL_Quit(); + + if (engine.demoQuit != NULL) + engine.demoQuit(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gtktimeline.c Mon Oct 15 22:48:41 2012 +0300 @@ -0,0 +1,212 @@ +#include "gtktimeline.h" + + +static void gtk_timeline_class_init(GtkTimelineClass *klass); +static void gtk_timeline_init(GtkTimeline *timeline); +static void gtk_timeline_size_request(GtkWidget *widget, GtkRequisition *requisition); +static void gtk_timeline_size_allocate(GtkWidget *widget, GtkAllocation *allocation); +static void gtk_timeline_realize(GtkWidget *widget); +static gboolean gtk_timeline_expose(GtkWidget *widget, GdkEventExpose *event); +static void gtk_timeline_paint(GtkWidget *widget); +static void gtk_timeline_destroy(GtkObject *object); + + +GtkType gtk_timeline_get_type(void) +{ + static GtkType gtk_timeline_type = 0; + + if (!gtk_timeline_type) + { + static const GtkTypeInfo gtk_timeline_info = + { + "GtkTimeline", + sizeof(GtkTimeline), + sizeof(GtkTimelineClass), + (GtkClassInitFunc) gtk_timeline_class_init, + (GtkObjectInitFunc) gtk_timeline_init, + NULL, + NULL, + (GtkClassInitFunc) NULL + }; + gtk_timeline_type = gtk_type_unique(GTK_TYPE_WIDGET, >k_timeline_info); + } + return gtk_timeline_type; +} + + +void gtk_timeline_set_zoom(GtkTimeline *timeline, gfloat zoom) +{ + timeline->zoom = zoom; + gtk_timeline_paint(GTK_WIDGET(timeline)); +} + + +void gtk_timeline_set_time(GtkTimeline *timeline, gint time) +{ + timeline->time = time; + gtk_timeline_paint(GTK_WIDGET(timeline)); +} + + +void gtk_timeline_set_offs(GtkTimeline *timeline, gint offs) +{ + timeline->offs = offs; + gtk_timeline_paint(GTK_WIDGET(timeline)); +} + + +GtkWidget * gtk_timeline_new() +{ + return GTK_WIDGET(gtk_type_new(gtk_timeline_get_type())); +} + + +static void gtk_timeline_class_init(GtkTimelineClass *klass) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *) klass; + GtkObjectClass *object_class = (GtkObjectClass *) klass; + + widget_class->realize = gtk_timeline_realize; + widget_class->size_request = gtk_timeline_size_request; + widget_class->size_allocate = gtk_timeline_size_allocate; + widget_class->expose_event = gtk_timeline_expose; + + object_class->destroy = gtk_timeline_destroy; +} + + +static void gtk_timeline_init(GtkTimeline *timeline) +{ + timeline->time = 0; + timeline->offs = 0; + timeline->zoom = 1.0f; + timeline->tl = NULL; +} + + +static void gtk_timeline_size_request(GtkWidget *widget, GtkRequisition *requisition) +{ + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_TIMELINE(widget)); + g_return_if_fail(requisition != NULL); + + requisition->width = 200; + requisition->height = 60; +} + + +static void gtk_timeline_size_allocate(GtkWidget *widget, + GtkAllocation *allocation) +{ + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_TIMELINE(widget)); + g_return_if_fail(allocation != NULL); + + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED(widget)) + { + gdk_window_move_resize( + widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + } +} + + +static void gtk_timeline_realize(GtkWidget *widget) +{ + GdkWindowAttr attributes; + guint attributes_mask; + + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_TIMELINE(widget)); + + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = 200; + attributes.height = 60; + + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + widget->window = gdk_window_new( + gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + + gdk_window_set_user_data(widget->window, widget); + + widget->style = gtk_style_attach(widget->style, widget->window); + gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); +} + + +static gboolean gtk_timeline_expose(GtkWidget *widget, GdkEventExpose *event) +{ + g_return_val_if_fail(widget != NULL, FALSE); + g_return_val_if_fail(GTK_IS_TIMELINE(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + gtk_timeline_paint(widget); + + return FALSE; +} + + +static void gtk_timeline_paint(GtkWidget *widget) +{ +#if 0 + gint i; + cairo_t *cr; + + cr = gdk_cairo_create(widget->window); + + cairo_translate(cr, 0, 7); + + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_paint(cr); + + gint pos = GTK_TIMELINE(widget)->sel; + gint rect = pos / 5; + + cairo_set_source_rgb(cr, 0.2, 0.4, 0); + + for (i = 1; i <= 20; i++) + { + if (i > 20 - rect) + cairo_set_source_rgb(cr, 0.6, 1.0, 0); + else + cairo_set_source_rgb(cr, 0.2, 0.4, 0); + + cairo_rectangle(cr, 8, i*4, 30, 3); + cairo_rectangle(cr, 42, i*4, 30, 3); + cairo_fill(cr); + } + + cairo_destroy(cr); +#endif +} + + +static void gtk_timeline_destroy(GtkObject *object) +{ + GtkTimeline *timeline; + GtkTimelineClass *klass; + + g_return_if_fail(object != NULL); + g_return_if_fail(GTK_IS_TIMELINE(object)); + + timeline = GTK_TIMELINE(object); + + klass = gtk_type_class(gtk_widget_get_type()); + + if (GTK_OBJECT_CLASS(klass)->destroy) + { + (* GTK_OBJECT_CLASS(klass)->destroy) (object); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gtktimeline.h Mon Oct 15 22:48:41 2012 +0300 @@ -0,0 +1,45 @@ +#ifndef GTKTIMELINE_H +#define GTKTIMELINE_H + +#include <gtk/gtk.h> +#include <cairo.h> + +#include "dmtimeline.h" + +G_BEGIN_DECLS + + +#define GTK_TIMELINE(obj) GTK_CHECK_CAST(obj, gtk_timeline_get_type (), GtkTimeline) +#define GTK_TIMELINE_CLASS(klass) GTK_CHECK_CLASS_CAST(klass, gtk_timeline_get_type(), GtkTimelineClass) +#define GTK_IS_TIMELINE(obj) GTK_CHECK_TYPE(obj, gtk_timeline_get_type()) + + +typedef struct _GtkTimeline GtkTimeline; +typedef struct _GtkTimelineClass GtkTimelineClass; + + +struct _GtkTimeline +{ + GtkWidget widget; + DMTimeline *tl; + gint time, offs; + gfloat zoom; +}; + +struct _GtkTimelineClass +{ + GtkWidgetClass parent_class; +}; + + +GtkType gtk_timeline_get_type(void); +void gtk_timeline_set_timeline(GtkTimeline *timeline, DMTimeline *tl); +void gtk_timeline_set_zoom(GtkTimeline *timeline, gfloat zoom); +void gtk_timeline_set_time(GtkTimeline *timeline, gint time); +void gtk_timeline_set_offs(GtkTimeline *timeline, gint offs); +GtkWidget * gtk_timeline_new(); + + +G_END_DECLS + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gtkwaveform.c Mon Oct 15 22:48:41 2012 +0300 @@ -0,0 +1,221 @@ +#include "gtkwaveform.h" + + +static void gtk_waveform_class_init(GtkWaveformClass *klass); +static void gtk_waveform_init(GtkWaveform *waveform); +static void gtk_waveform_size_request(GtkWidget *widget, GtkRequisition *requisition); +static void gtk_waveform_size_allocate(GtkWidget *widget, GtkAllocation *allocation); +static void gtk_waveform_realize(GtkWidget *widget); +static gboolean gtk_waveform_expose(GtkWidget *widget, GdkEventExpose *event); +static void gtk_waveform_paint(GtkWidget *widget); +static void gtk_waveform_destroy(GtkObject *object); + + +GtkType gtk_waveform_get_type(void) +{ + static GtkType gtk_waveform_type = 0; + + if (!gtk_waveform_type) + { + static const GtkTypeInfo gtk_waveform_info = + { + "GtkWaveform", + sizeof(GtkWaveform), + sizeof(GtkWaveformClass), + (GtkClassInitFunc) gtk_waveform_class_init, + (GtkObjectInitFunc) gtk_waveform_init, + NULL, + NULL, + (GtkClassInitFunc) NULL + }; + gtk_waveform_type = gtk_type_unique(GTK_TYPE_WIDGET, >k_waveform_info); + } + return gtk_waveform_type; +} + + +void gtk_waveform_set_wave_data(GtkWaveform *waveform, gint16 *data, gint len, gint freq) +{ + waveform->data = data; + waveform->len = len; + waveform->freq = freq; + gtk_waveform_paint(GTK_WIDGET(waveform)); +} + + +void gtk_waveform_set_zoom(GtkWaveform *waveform, gfloat zoom) +{ + waveform->zoom = zoom; + gtk_waveform_paint(GTK_WIDGET(waveform)); +} + + +void gtk_waveform_set_time(GtkWaveform *waveform, gint time) +{ + waveform->time = time; + gtk_waveform_paint(GTK_WIDGET(waveform)); +} + + +void gtk_waveform_set_offs(GtkWaveform *waveform, gint offs) +{ + waveform->offs = offs; + gtk_waveform_paint(GTK_WIDGET(waveform)); +} + + +GtkWidget * gtk_waveform_new() +{ + return GTK_WIDGET(gtk_type_new(gtk_waveform_get_type())); +} + + +static void gtk_waveform_class_init(GtkWaveformClass *klass) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *) klass; + GtkObjectClass *object_class = (GtkObjectClass *) klass; + + widget_class->realize = gtk_waveform_realize; + widget_class->size_request = gtk_waveform_size_request; + widget_class->size_allocate = gtk_waveform_size_allocate; + widget_class->expose_event = gtk_waveform_expose; + + object_class->destroy = gtk_waveform_destroy; +} + + +static void gtk_waveform_init(GtkWaveform *waveform) +{ + waveform->time = 0; + waveform->offs = 0; + waveform->zoom = 1.0f; + waveform->data = NULL; + waveform->freq = 1; +} + + +static void gtk_waveform_size_request(GtkWidget *widget, GtkRequisition *requisition) +{ + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_WAVEFORM(widget)); + g_return_if_fail(requisition != NULL); + + requisition->width = 200; + requisition->height = 60; +} + + +static void gtk_waveform_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_WAVEFORM(widget)); + g_return_if_fail(allocation != NULL); + + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED(widget)) + { + gdk_window_move_resize( + widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + } +} + + +static void gtk_waveform_realize(GtkWidget *widget) +{ + GdkWindowAttr attributes; + guint attributes_mask; + + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_WAVEFORM(widget)); + + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = 80; + attributes.height = 100; + + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + widget->window = gdk_window_new( + gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + + gdk_window_set_user_data(widget->window, widget); + + widget->style = gtk_style_attach(widget->style, widget->window); + gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); +} + + +static gboolean gtk_waveform_expose(GtkWidget *widget, GdkEventExpose *event) +{ + g_return_val_if_fail(widget != NULL, FALSE); + g_return_val_if_fail(GTK_IS_WAVEFORM(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + gtk_waveform_paint(widget); + + return FALSE; +} + + +static void gtk_waveform_paint(GtkWidget *widget) +{ +#if 0 + gint i; + cairo_t *cr; + + cr = gdk_cairo_create(widget->window); + + cairo_translate(cr, 0, 7); + + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_paint(cr); + + gint pos = GTK_WAVEFORM(widget)->sel; + gint rect = pos / 5; + + cairo_set_source_rgb(cr, 0.2, 0.4, 0); + + for (i = 1; i <= 20; i++) + { + if (i > 20 - rect) + cairo_set_source_rgb(cr, 0.6, 1.0, 0); + else + cairo_set_source_rgb(cr, 0.2, 0.4, 0); + + cairo_rectangle(cr, 8, i*4, 30, 3); + cairo_rectangle(cr, 42, i*4, 30, 3); + cairo_fill(cr); + } + + cairo_destroy(cr); +#endif +} + + +static void gtk_waveform_destroy(GtkObject *object) +{ + GtkWaveform *waveform; + GtkWaveformClass *klass; + + g_return_if_fail(object != NULL); + g_return_if_fail(GTK_IS_WAVEFORM(object)); + + waveform = GTK_WAVEFORM(object); + + klass = gtk_type_class(gtk_widget_get_type()); + + if (GTK_OBJECT_CLASS(klass)->destroy) + { + (* GTK_OBJECT_CLASS(klass)->destroy) (object); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gtkwaveform.h Mon Oct 15 22:48:41 2012 +0300 @@ -0,0 +1,43 @@ +#ifndef GTKWAVEFORM_H +#define GTKWAVEFORM_H + +#include <gtk/gtk.h> +#include <cairo.h> + +G_BEGIN_DECLS + + +#define GTK_WAVEFORM(obj) GTK_CHECK_CAST(obj, gtk_waveform_get_type (), GtkWaveform) +#define GTK_WAVEFORM_CLASS(klass) GTK_CHECK_CLASS_CAST(klass, gtk_waveform_get_type(), GtkWaveformClass) +#define GTK_IS_WAVEFORM(obj) GTK_CHECK_TYPE(obj, gtk_waveform_get_type()) + + +typedef struct _GtkWaveform GtkWaveform; +typedef struct _GtkWaveformClass GtkWaveformClass; + + +struct _GtkWaveform +{ + GtkWidget widget; + gint16 *data; + gint len, time, offs, freq; + gfloat zoom; +}; + +struct _GtkWaveformClass +{ + GtkWidgetClass parent_class; +}; + + +GtkType gtk_waveform_get_type(void); +void gtk_waveform_set_wave_data(GtkWaveform *waveform, gint16 *data, gint len, gint freq); +void gtk_waveform_set_zoom(GtkWaveform *waveform, gfloat zoom); +void gtk_waveform_set_time(GtkWaveform *waveform, gint time); +void gtk_waveform_set_offs(GtkWaveform *waveform, gint offs); +GtkWidget * gtk_waveform_new(); + + +G_END_DECLS + +#endif