/*************************************************
*   a gtk widget for displaying of waveforms     *
*   supporting a play selection, a rec-selection *
*   zooming and various mouse-actions	    *
*   written by dieb13 at klingt.org 2003/2004    *
**************************************************/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <gdk/gdkkeysyms.h>
#include "gtkloopview.h"
#include "../../common/looperdata.h"

#define SCROLL_DELAY_LENGTH  300
#define LOOPVIEW_DEFAULT_WIDTH  100
#define LOOPVIEW_DEFAULT_HEIGHT  50

static guint gtk_loopview_signals[LAST_SIGNAL] = { 0 };

static GtkWidgetClass *parent_class = NULL;

/* forward declarations */
GtkType gtk_loopview_get_type (void);
static void gtk_loopview_class_init (GtkLoopviewClass *class);
static void gtk_loopview_init (GtkLoopview *loopview);
GtkWidget* gtk_loopview_new (looper_data_t *looperdata);
static void gtk_loopview_destroy (GtkObject *object);
looper_data_t* gtk_loopview_get_looperdata (GtkLoopview *loopview);
void gtk_loopview_set_update_policy (GtkLoopview      *loopview,GtkUpdateType  policy);
void gtk_loopview_update_gplayposition (GtkLoopview *loopview);
void gtk_loopview_set_looperdata (GtkLoopview      *loopview,looper_data_t *looperdata);
void gtk_loopview_update_waveform (GtkLoopview *loopview);
/*void gtk_loopview_calc_peaks(GtkLoopview *loopview,guint32 startx, guint32 endx);*/
void gtk_loopview_copy_peaks(GtkLoopview *loopview, peakdata_t *pd);
static void gtk_loopview_realize (GtkWidget *widget);
static void gtk_loopview_size_request (GtkWidget      *widget, GtkRequisition *requisition);
static void gtk_loopview_size_allocate (GtkWidget     *widget, GtkAllocation *allocation);
static gboolean gtk_loopview_expose( GtkWidget      *widget,GdkEventExpose *event );
static gboolean gtk_loopview_button_press( GtkWidget      *widget, GdkEventButton *event );
static gboolean gtk_loopview_button_release( GtkWidget      *widget, GdkEventButton *event );
static gboolean gtk_loopview_motion_notify( GtkWidget      *widget,GdkEventMotion *event );
/*
static gboolean gtk_loopview_key_release_notify( GtkWidget *widget,GdkEventKey *key);
static gboolean gtk_loopview_key_press_notify( GtkWidget *widget,GdkEventKey *key);
*/
static gint gtk_loopview_focus_in (GtkWidget * widget, GdkEventFocus * event);
static gint gtk_loopview_focus_out (GtkWidget * widget, GdkEventFocus * event);
static gint gtk_loopview_enter_notify (GtkWidget *widget, GdkEventCrossing *event);
static gint gtk_loopview_leave_notify (GtkWidget *widget, GdkEventCrossing *event);
/*static gboolean gtk_loopview_timer( GtkLoopview *loopview );*/
static void gtk_loopview_update_mouse (GtkLoopview *loopview, gint x, gint y);
/*static void gtk_loopview_update (GtkLoopview *loopview);*/


/* functions */


GtkType gtk_loopview_get_type ()
{
  	static GtkType loopview_type = 0;

  	if (!loopview_type){
      		static const GtkTypeInfo loopview_info =
      		{
			"GtkLoopview",
			sizeof (GtkLoopview),
			sizeof (GtkLoopviewClass),
			(GtkClassInitFunc) gtk_loopview_class_init,
			(GtkObjectInitFunc) gtk_loopview_init,
			/* reserved_1 */ NULL,
			/* reserved_1 */ NULL,
			(GtkClassInitFunc) NULL
      		};
      		loopview_type = gtk_type_unique (GTK_TYPE_WIDGET, &loopview_info);
    	}

  	return loopview_type;
}


static void gtk_loopview_class_init (GtkLoopviewClass *class){
  	GtkObjectClass *object_class;
  	GtkWidgetClass *widget_class;

  	object_class = (GtkObjectClass*) class;
  	widget_class = (GtkWidgetClass*) class;

  	parent_class = gtk_type_class (gtk_widget_get_type ());
	
  	object_class->destroy = gtk_loopview_destroy;

  	widget_class->realize = gtk_loopview_realize;
  	widget_class->expose_event = gtk_loopview_expose;
  	widget_class->size_request = gtk_loopview_size_request;
  	widget_class->size_allocate = gtk_loopview_size_allocate;
  	widget_class->button_press_event = gtk_loopview_button_press;
  	widget_class->button_release_event = gtk_loopview_button_release;
  	widget_class->motion_notify_event = gtk_loopview_motion_notify;
/*
	widget_class->key_release_event = gtk_loopview_key_release_notify;
	widget_class->key_press_event = gtk_loopview_key_press_notify;
*/

	widget_class->focus_in_event = gtk_loopview_focus_in;
  	widget_class->focus_out_event = gtk_loopview_focus_out;
	widget_class->enter_notify_event = gtk_loopview_enter_notify;
	widget_class->leave_notify_event = gtk_loopview_leave_notify;

	gtk_loopview_signals[SIG_LOOPBORDERS_CHANGED] = 
	g_signal_new ("loopborders-changed",
		G_TYPE_FROM_CLASS (object_class),
		G_SIGNAL_RUN_FIRST,
		0,
		NULL, 
		NULL,		
		g_cclosure_marshal_VOID__VOID,
		G_TYPE_NONE, 0, NULL);

	gtk_loopview_signals[SIG_RECBORDERS_CHANGED] =
	g_signal_new ("recborders-changed",
		G_TYPE_FROM_CLASS (object_class),
		G_SIGNAL_RUN_FIRST,
		0,
		NULL,
		NULL,
		g_cclosure_marshal_VOID__VOID,
		G_TYPE_NONE, 0, NULL);

	gtk_loopview_signals[SIG_ZOOMBORDERS_CHANGED] =
	g_signal_new ("zoomborders-changed",
		G_TYPE_FROM_CLASS (object_class),
		G_SIGNAL_RUN_FIRST,
		0,
		NULL,
		NULL,
		g_cclosure_marshal_VOID__VOID,
		G_TYPE_NONE, 0, NULL);
	gtk_loopview_signals[SIG_SPEED_CHANGED] =
	g_signal_new ("speed-changed",
		G_TYPE_FROM_CLASS (object_class),
		G_SIGNAL_RUN_FIRST,
		0,
		NULL,
		NULL,
		g_cclosure_marshal_VOID__VOID,
		G_TYPE_NONE, 0, NULL);


	class->loopborders_changed = NULL;

}


static void gtk_loopview_init (GtkLoopview *loopview) {
  	loopview->button = 0;
  	loopview->policy = GTK_UPDATE_CONTINUOUS;
  	loopview->timer = 0;
	loopview->suspended = FALSE;
	loopview->peakview = NULL;
  	loopview->looperdata = looperdata_new(NULL,44100, 0);
/*	loopview->buffer_group = 0;*/
  	loopview->Lmin = NULL;
  	loopview->Rmin = NULL;
	loopview->Lmax = NULL;
	loopview->Rmax = NULL;
	loopview->npeaks = 0;
	loopview->lastnup = 0;
	loopview->width = 0;
	loopview->height = 0;
	loopview->Lmid = 0;
	loopview->Rmid = 0;
	loopview->Hmax = 0;
	loopview->zoomstart = 0;
	loopview->zoomend = 0;
	loopview->gzoomstart = 0;
	loopview->gzoomend = 0;
	loopview->gloopstart = 0;
	loopview->gloopend = 0;
	loopview->grecstart = 0;
	loopview->grecend = 0;
	loopview->gplaypos = 0;
	loopview->grecpos = 0;
	loopview->grabsel = 0;
	loopview->lastmouseX = 0;
	loopview->lastmouseY = 0;
	loopview->bpm = 120;
	loopview->bpb = 4;
	loopview->gridwidth = 22050;
	loopview->gridoffset = 0;
	loopview->ggridstart = 0;
	loopview->ggridwidth = 1;
	loopview->snap2grid = FALSE;
	loopview->showgrid = FALSE;
	loopview->showattac = TRUE;

	loopview->fgc = NULL;
	loopview->bgc = NULL;
	loopview->bg_plain = (GdkColor){0, 0, 0, 16535};
	loopview->bg_play = (GdkColor){0, 0, 0, 32767};
	loopview->bg_rec = (GdkColor){0, 32767, 0, 0};
	loopview->bg_zoom = (GdkColor){0, 0, 32767, 0};
	loopview->bg_recplay = (GdkColor){0, 32767, 0, 32767};
	loopview->bg_reczoom = (GdkColor){0, 32767, 32767, 0};
	loopview->bg_playzoom = (GdkColor){0, 0, 32767, 32767};
	loopview->bg_recplayzoom = (GdkColor){0, 32767, 32767, 32767};
	loopview->bg_grid = (GdkColor){0, 32767, 32767, 32767};
	loopview->bg_bar = (GdkColor){0, 65535, 65535, 65535};
	loopview->bg_beat = (GdkColor){0, 32767, 32767, 32767};
	loopview->fg_plain = (GdkColor){0, 32767, 32767, 0};
	loopview->fg_lit = (GdkColor){0, 65535, 65535, 0};
	loopview->playcursor = (GdkColor){0, 0, 65535, 0};
	loopview->reccursor = (GdkColor){0, 65535, 0, 0};

	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_plain);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_play);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_rec);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_zoom);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_recplay);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_reczoom);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_playzoom);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_recplayzoom);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_grid);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_bar);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_beat);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->fg_plain);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->fg_lit);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->playcursor);
	gdk_color_alloc (gdk_colormap_get_system (), &loopview->reccursor);

}

GtkWidget* gtk_loopview_new (looper_data_t * looperdata)
{
  	GtkLoopview *loopview;

  	loopview = gtk_type_new (gtk_loopview_get_type ());
  	gtk_loopview_set_looperdata (loopview, looperdata);
	gtk_loopview_update_waveform(loopview);
  	return GTK_WIDGET (loopview);
}

static void gtk_loopview_destroy (GtkObject *object)
{
  	GtkLoopview *loopview;

  	g_return_if_fail (object != NULL);
  	g_return_if_fail (GTK_IS_LOOPVIEW (object));

  	loopview = GTK_LOOPVIEW (object);
	if (loopview->peakview) peakview_delete(loopview->peakview);

  	if (GTK_OBJECT_CLASS (parent_class)->destroy)
    		(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}


looper_data_t* gtk_loopview_get_looperdata (GtkLoopview *loopview)
{
  	g_return_val_if_fail (loopview != NULL, NULL);
  	g_return_val_if_fail (GTK_IS_LOOPVIEW (loopview), NULL);

  	return loopview->looperdata;
}

void gtk_loopview_set_update_policy (GtkLoopview      *loopview,
			     GtkUpdateType  policy)
{
  	g_return_if_fail (loopview != NULL);
  	g_return_if_fail (GTK_IS_LOOPVIEW (loopview));

  	loopview->policy = policy;
}

void gtk_loopview_suspend_gui (GtkLoopview *loopview, int suspend){
	g_return_if_fail (loopview != NULL);
        g_return_if_fail (GTK_IS_LOOPVIEW (loopview));

	if (suspend){
		loopview->suspended = TRUE;
		if (loopview->peakview) peakview_clear(loopview->peakview, 0, 0);
	} else {
		loopview->suspended = FALSE;
		if (loopview->looperdata)
			if (loopview->looperdata->buf){
                        	if (!loopview->peakview)
					loopview->peakview = peakview_new(loopview->looperdata->buf);

				peakview_set_area(loopview->peakview,loopview->zoomstart,
                                                	loopview->zoomend, loopview->npeaks);
				peakview_calculate(loopview->peakview,loopview->zoomstart, 
						loopview->zoomend);
			}
	}
}

void gtk_loopview_set_looperdata (GtkLoopview *loopview, looper_data_t *looperdata){
  	g_return_if_fail (loopview != NULL);
  	g_return_if_fail (GTK_IS_LOOPVIEW (loopview));

  	loopview->looperdata = looperdata;
	loopview->zoomstart = 0;
	loopview->zoomend = 0;
/*
	if (loopview->peakview) {
		peakview_delete(loopview->peakview);
		loopview->peakview = NULL;
	}
*/
	if (loopview->looperdata->buf){
		loopview->zoomend = buffer_get_size(loopview->looperdata->buf);
		if (!loopview->peakview)
			loopview->peakview = peakview_new(loopview->looperdata->buf);
		else peakview_set_buffer(loopview->peakview, loopview->looperdata->buf);
		peakview_set_area(loopview->peakview,loopview->zoomstart, 
						loopview->zoomend, loopview->npeaks);
	}else{
		peakview_set_buffer(loopview->peakview, NULL);
		gtk_loopview_update_area(loopview,0,loopview->npeaks);
	}
	gtk_loopview_set_bpm(loopview,120);
/*	peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend);*/
/*	gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/

/*	gtk_loopview_update (loopview);*/
}

void gtk_loopview_update_waveform (GtkLoopview *loopview){
	g_return_if_fail (loopview != NULL);
	g_return_if_fail (GTK_IS_LOOPVIEW (loopview));

	if (loopview->looperdata->buf && !loopview->suspended)
		peakview_calculate(loopview->peakview,0, loopview->zoomend);
	else gtk_loopview_update_area(loopview,0,loopview->npeaks);
/*	gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/
/*	gtk_loopview_update (loopview);*/
}

static gint32 gtk_loopview_sample2graphical (GtkLoopview *loopview, gdouble sample){
	gint64 gr;

	gr = (gint64)(loopview->zoomend - loopview->zoomstart);
	if (gr){
		gr = (gint64)(sample - loopview->zoomstart ) * loopview->npeaks / gr;
		return (gint32)gr;
	}else{
		return 0;
	}
}

static gdouble gtk_loopview_graphical2sample (GtkLoopview *loopview, gint32 gr){
	gdouble sample;

	if (!loopview->npeaks){
		return 0;
	}else{
		sample = (gdouble)loopview->zoomstart + 
		 	(gdouble)gr  * 
		 	(gdouble)(loopview->zoomend - loopview->zoomstart) /
		 	(gdouble)loopview->npeaks;
		return sample;
	}
}

void gtk_loopview_set_play_pos (GtkLoopview *loopview, gdouble playpos){
	gint32 temp,t2;

	if (loopview->looperdata){
		temp = gtk_loopview_sample2graphical (loopview,playpos);
		if (temp < 0){temp = 0;}
		if (temp > loopview->npeaks){temp = loopview->npeaks;}

		if (temp != loopview->gplaypos){
			t2 = loopview->gplaypos;
			loopview->gplaypos = temp;
/*			printf ("playcursor: %d -> %d\n",(int)t2,(int)temp);*/
			if (abs(loopview->gplaypos - t2) < 3){
				gtk_loopview_update_area(loopview,t2,loopview->gplaypos);
			}else{
				gtk_loopview_update_area(loopview,t2,t2);
				gtk_loopview_update_area(loopview,loopview->gplaypos,loopview->gplaypos);
			}
/*			printf ("playcursor\n");*/
	
		}
	}
}

void gtk_loopview_set_rec_pos (GtkLoopview *loopview, gdouble recpos){
	gint32 temp,t2;

	if (loopview->looperdata){
		temp = gtk_loopview_sample2graphical (loopview,recpos);
		if (temp < 0){temp = 0;}
		if (temp > loopview->npeaks){temp = loopview->npeaks;}
		
		if (temp != loopview->grecpos){
			t2 = loopview->grecpos;
			loopview->grecpos = temp;
			if (abs(loopview->grecpos - t2) < 3){
/*				printf ("recpos update: %ld - %ld\n",t2,loopview->grecpos);*/
				gtk_loopview_update_area(loopview,t2,loopview->grecpos);
			}else{
/*				printf ("recpos update: %ld , %ld\n",t2,loopview->grecpos);*/
				gtk_loopview_update_area(loopview,t2,t2);
				gtk_loopview_update_area(loopview,loopview->grecpos,loopview->grecpos);
			}
		}
	}
}

void gtk_loopview_zoom_to_playselection (GtkLoopview *loopview){
	if (loopview->looperdata){
	       	loopview->zoomstart = loopview->looperdata->loopstart;
		loopview->zoomend = loopview->looperdata->loopend;
		loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart);
		loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend);
		loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart);
		loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend);
/*		gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/
		peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks);
		if (!loopview->suspended)
			peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend);
	}
}

void gtk_loopview_zoom_to_recselection (GtkLoopview *loopview){
	if (loopview->looperdata){
		loopview->zoomstart = loopview->looperdata->recstart;
		loopview->zoomend = loopview->looperdata->recend;
		loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart);
		loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend);
		loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart);
		loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend);
/*		gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/
		peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks);
		if (!loopview->suspended)
                	peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend);
	}
}

void gtk_loopview_zoom_to_overview (GtkLoopview *loopview){
	if (loopview->looperdata){
		loopview->zoomstart = 0;
		loopview->zoomend = 0;
		if (loopview->looperdata)
			if (loopview->looperdata->buf)
				loopview->zoomend = buffer_get_size(loopview->looperdata->buf);
		loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart);
		loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend);
		loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart);
		loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend);
/*		gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/
		peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks);
		if (!loopview->suspended)
                	peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend);
	}
}

void gtk_loopview_set_zoom (GtkLoopview *loopview, gdouble zoomstart, gdouble zoomend){
	gdouble temp;

/*	printf ("set zoom\n");*/
	if (zoomend < zoomstart){
		temp = zoomend;
		zoomend = zoomstart;
		zoomstart = temp;
	}

	if (loopview->looperdata){
		if ((loopview->zoomstart == zoomstart) && (loopview->zoomend == zoomend)) return;
		if (loopview->looperdata->buf){
			if (zoomend < 0) zoomend = 0;
			if (zoomend > buffer_get_size(loopview->looperdata->buf)) 
				zoomend = buffer_get_size(loopview->looperdata->buf);
			if (zoomstart < 0) zoomstart = 0;
			if (zoomstart > buffer_get_size(loopview->looperdata->buf)) 
				zoomstart = buffer_get_size(loopview->looperdata->buf);

			if (zoomstart < zoomend){					
				loopview->zoomstart = zoomstart;
				loopview->zoomend = zoomend;
				loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart);
				loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend);
				loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart);
				loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend);
/*				gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/
				peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks);
				if (!loopview->suspended)
                			peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend);
			}
		}
	}
}

long  gtk_loopview_get_zoomstart (GtkLoopview *loopview){
	if (loopview->looperdata)
		if (loopview->looperdata->buf)
			return (long)loopview->zoomstart;

	return 0;
}

long gtk_loopview_get_zoomend (GtkLoopview *loopview){
	if (loopview->looperdata)
		if (loopview->looperdata->buf)
			return (long)loopview->zoomend;

	return 0;
}

void gtk_loopview_update_loopstart (GtkLoopview *loopview){
	gint32 temp = loopview->gloopstart;

	loopview->gloopstart = 
		gtk_loopview_sample2graphical(loopview,
			(gdouble)looperdata_get_loopstart(loopview->looperdata));

	gtk_loopview_update_area (loopview,
		MIN (temp, loopview->gloopstart),
		MAX (temp, loopview->gloopstart));
}

void gtk_loopview_update_loopend (GtkLoopview *loopview){
	gint32 temp = loopview->gloopend;

	loopview->gloopend =
		gtk_loopview_sample2graphical(loopview,
			(gdouble)looperdata_get_loopend(loopview->looperdata));

	gtk_loopview_update_area (loopview,
		MIN (temp, loopview->gloopend),
		MAX (temp, loopview->gloopend));
}

void gtk_loopview_update_recstart (GtkLoopview *loopview){
	gint32 temp = loopview->grecstart;

	loopview->grecstart =
		gtk_loopview_sample2graphical(loopview,
			(gdouble)loopview->looperdata->recstart);

	gtk_loopview_update_area (loopview,
		MIN (temp, loopview->grecstart),
		MAX (temp, loopview->grecstart));
}

void gtk_loopview_set_snap2grid (GtkLoopview *loopview, gboolean snap){
	loopview->snap2grid = snap;
}

gboolean gtk_loopview_getsnap2grid (GtkLoopview *loopview){
	return loopview->snap2grid;
}

void gtk_loopview_set_showgrid (GtkLoopview *loopview, gboolean show){
	loopview->showgrid = show;
	gtk_loopview_update_area (loopview,0,loopview->npeaks);
}

gboolean gtk_loopview_get_showgrid (GtkLoopview *loopview){
	return loopview->showgrid;

}

void gtk_loopview_set_bpm (GtkLoopview *loopview, gdouble bpm){
	if (bpm > 0.0001) {
		loopview->bpm = bpm;
		if (loopview->looperdata){
			loopview->gridwidth = loopview->looperdata->samplerate  * 60. / bpm;
		}
		gtk_loopview_update_area (loopview,0,loopview->npeaks);
	}
}

gdouble gtk_loopview_get_bpm (GtkLoopview *loopview){
	return loopview->bpm;
}

void gtk_loopview_set_gridoffset (GtkLoopview *loopview, guint32 offset){
	if (loopview->looperdata){
		if (loopview->looperdata->buf){
			if(offset <= buffer_get_size(loopview->looperdata->buf))
				loopview->gridoffset = offset;
			else loopview->gridoffset = buffer_get_size(loopview->looperdata->buf);
/*			printf ("offset:%ld\n",(long)loopview->gridoffset);*/
			gtk_loopview_update_area (loopview,0,loopview->npeaks);
		} else loopview->gridoffset = 0;
	} else loopview->gridoffset = 0;
}

guint32 gtk_loopview_get_gridoffset (GtkLoopview *loopview){
	return loopview->gridoffset;
}

guint32 gtk_loopview_get_gridwidth (GtkLoopview *loopview){
        return loopview->gridwidth;
}

void gtk_loopview_set_bpb (GtkLoopview *loopview, gdouble bpb){
	if (bpb >= 1.){
		loopview->bpb = bpb;
		gtk_loopview_update_area (loopview,0,loopview->npeaks);
	}
}

gdouble gtk_loopview_get_bpb (GtkLoopview *loopview){
	return loopview->bpb;
}

void gtk_loopview_update_recend (GtkLoopview *loopview){
	gint32 temp = loopview->grecend;

	loopview->grecend =
		gtk_loopview_sample2graphical(loopview,
			(gdouble)loopview->looperdata->recend);

	gtk_loopview_update_area (loopview,
		MIN (temp, loopview->grecend),
		MAX (temp, loopview->grecend));
}

void gtk_loopview_update_cursorposition (GtkLoopview *loopview){
	g_return_if_fail (loopview != NULL);
	g_return_if_fail (GTK_IS_LOOPVIEW (loopview));
	double start = 0.;
	double end = 0.;
	gint x = 0;
	gint y = 0;
	GdkModifierType mods;
	peakdata_t *pd;

	if (loopview->looperdata){
		if (loopview->looperdata->buf){
			gdk_window_get_pointer (GTK_WIDGET(loopview)->window, &x, &y, &mods);

//			looperdata_lock(loopview->looperdata);
			while (looperdata_read_once_dirtyblock(loopview->looperdata, &start, &end)){
				if (!loopview->suspended){
/*					printf ("dirtyblock: %.2lf - %.2lf\n", start, end);*/
					peakview_calculate(loopview->peakview, (long)start, (long)end);
				}
			}
//			looperdata_unlock(loopview->looperdata);

			if (loopview->peakview){
				peakview_lock(loopview->peakview);
				while ((pd = peakview_get_next(loopview->peakview))){
					gtk_loopview_copy_peaks(loopview,pd);
				}
				peakview_unlock(loopview->peakview);
			}
			gtk_loopview_set_play_pos (loopview,
				looperdata_get_playpos(loopview->looperdata));
			gtk_loopview_set_rec_pos (loopview,
				(double)looperdata_get_recpos(loopview->looperdata));
		}
	}
}

static void gtk_loopview_realize (GtkWidget *widget)
{
  	/*GtkLoopview *loopview;*/
  	GdkWindowAttr attributes;
  	gint attributes_mask;

  	g_return_if_fail (widget != NULL);
  	g_return_if_fail (GTK_IS_LOOPVIEW (widget));
	
  	GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
  	/*loopview = GTK_LOOPVIEW (widget);*/
	
  	attributes.x = widget->allocation.x;
  	attributes.y = widget->allocation.y;
  	attributes.width = widget->allocation.width;
  	attributes.height = widget->allocation.height;
  	attributes.wclass = GDK_INPUT_OUTPUT;
  	attributes.window_type = GDK_WINDOW_CHILD;
/*
  	attributes.event_mask = (gtk_widget_get_events (widget) | 
    		GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
    		GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
    		GDK_POINTER_MOTION_HINT_MASK | GDK_KEY_PRESS_MASK |
		GDK_KEY_RELEASE_MASK );
*/
	attributes.event_mask = GDK_ALL_EVENTS_MASK;
	
  	attributes.visual = gtk_widget_get_visual (widget);
  	attributes.colormap = gtk_widget_get_colormap (widget);

  	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
  	widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);

  	widget->style = gtk_style_attach (widget->style, widget->window);
	
  	gdk_window_set_user_data (widget->window, widget);
	
  	gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);

	gtk_widget_add_events(widget, GDK_ALL_EVENTS_MASK);
/*	printf ("realized\n");*/
}

static void gtk_loopview_size_request (GtkWidget      *widget,
		       GtkRequisition *requisition)
{
  	requisition->width = LOOPVIEW_DEFAULT_WIDTH;
  	requisition->height = LOOPVIEW_DEFAULT_HEIGHT;
}

static void gtk_loopview_size_allocate (GtkWidget     *widget,
			GtkAllocation *allocation)
{
  	GtkLoopview *loopview;

  	g_return_if_fail (widget != NULL);
  	g_return_if_fail (GTK_IS_LOOPVIEW (widget));
  	g_return_if_fail (allocation != NULL);

  	widget->allocation = *allocation;
  	if (GTK_WIDGET_REALIZED (widget)){
      		loopview = GTK_LOOPVIEW (widget);
/*		printf ("size allocate:%ldx%ld\n",(long)allocation->width,(long)allocation->height);*/

      		gdk_window_move_resize (widget->window,
			      allocation->x, allocation->y,
			      allocation->width, allocation->height);

		/* reinitialize the offscreen pixmap */
		if (loopview->pixmap) g_object_unref(loopview->pixmap);
		loopview->pixmap = gdk_pixmap_new(widget->window,allocation->width,allocation->height,-1);
		

		if (loopview->width != allocation->width){	
			if (loopview->npeaks){
				loopview->gloopstart = loopview->gloopstart * allocation->width / loopview->npeaks;
				loopview->gloopend   = loopview->gloopend   * allocation->width / loopview->npeaks;
				loopview->grecstart  = loopview->grecstart  * allocation->width / loopview->npeaks;
				loopview->grecend    = loopview->grecend    * allocation->width / loopview->npeaks;
			}

		       	loopview->Lmin = realloc (loopview->Lmin,sizeof(gint8) * (allocation->width + 1));
			memset(loopview->Lmin,0,sizeof(gint8) * allocation->width);
		       	loopview->Lmax = realloc (loopview->Lmax,sizeof(gint8) * (allocation->width + 1));
			memset(loopview->Lmax,0,sizeof(gint8) * allocation->width);
			loopview->Rmin = realloc (loopview->Rmin,sizeof(gint8) * (allocation->width + 1));
			memset(loopview->Rmin,0,sizeof(gint8) * allocation->width);
			loopview->Rmax = realloc (loopview->Rmax,sizeof(gint8) * (allocation->width + 1));
			memset(loopview->Rmax,0,sizeof(gint8) * allocation->width);

			loopview->npeaks = allocation->width;
			loopview->width = allocation->width;
			loopview->height = allocation->height;
/*			gtk_loopview_calc_peaks(loopview,0,allocation->width);*/

			peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, allocation->width);
			if (!loopview->suspended)
				peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend);
			gtk_loopview_update_area(loopview,0,allocation->width);
		} else if (loopview->height != allocation->height){
			loopview->height = allocation->height;
			gtk_loopview_update_area(loopview,0,allocation->width);
		} else{
			gtk_loopview_update_area(loopview,0,allocation->width);
		}
    	}/*else printf("not realized\n");*/
}

void gtk_loopview_update_column (GtkLoopview *loopview, int i){
/*	float d1, d2;*/
	gdouble diff = 0.;

	if (i == loopview->grecpos){
		gdk_gc_set_foreground(loopview->fgc,&loopview->reccursor);
		gdk_draw_line (loopview->pixmap,loopview->fgc,loopview->grecpos,1,
			loopview->grecpos,loopview->height);
	}else if (i == loopview->gplaypos){
		gdk_gc_set_foreground(loopview->fgc,&loopview->playcursor);
		gdk_draw_line (loopview->pixmap,loopview->fgc,loopview->gplaypos,1,
			loopview->gplaypos,loopview->height);
	}else{
		if (loopview->showgrid){        
                        diff = (gtk_loopview_graphical2sample(loopview,i) - loopview->gridoffset) / loopview->gridwidth;
                        diff = gtk_loopview_sample2graphical(loopview,(gint)(diff + .5) * loopview->gridwidth + loopview->gridoffset);
                        diff = fabs(diff - i);
                }

		if ((loopview->showgrid) && (diff < .5)){
			if (((int)((float)gtk_loopview_graphical2sample(loopview,i) / (float)loopview->gridwidth + .5) 
					% (int)loopview->bpb) == 0)
				gdk_gc_set_foreground(loopview->bgc,&loopview->bg_bar);
			else
				gdk_gc_set_foreground(loopview->bgc,&loopview->bg_beat);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_plain);
		}else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend) &&
			(i >= loopview->grecstart) && (i <= loopview->grecend) &&
			(i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_recplayzoom);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit);
		}else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend) &&
			(i >= loopview->grecstart) && (i <= loopview->grecend)){
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_recplay);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit);
		}else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend) &&
			(i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_playzoom);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit);
		}else if ((i >= loopview->grecstart) && (i <= loopview->grecend) &&
			(i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_reczoom);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit);
		}else if ((i >= loopview->grecstart) && (i <= loopview->grecend)){
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_rec);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit);
		}else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend)){
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_play);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit);
		}else if ((i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_zoom);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit);
		}else{
			gdk_gc_set_foreground(loopview->bgc,&loopview->bg_plain);
			gdk_gc_set_foreground(loopview->fgc,&loopview->fg_plain);
		}
	
		gdk_draw_line (loopview->pixmap,loopview->bgc,
			i,0,i,loopview->height);
	
		gdk_draw_line (loopview->pixmap,loopview->fgc,
			i,loopview->Lmid + (*(loopview->Lmin + i) * loopview->Hmax) / 127,
			i,loopview->Lmid + (*(loopview->Lmax + i) * loopview->Hmax) / 127);
	
		if (buffer_get_channels(loopview->looperdata->buf) > 1)
			gdk_draw_line (loopview->pixmap,loopview->fgc,
				i,loopview->Rmid + (*(loopview->Rmin + i) * loopview->Hmax) / 127,
				i,loopview->Rmid + (*(loopview->Rmax + i) * loopview->Hmax) / 127);
/*		printf ("updated:%d\n",(int)i);*/
	}
/*	printf ("updated:%d,height: %d\n",(int)i,(int)loopview->height);*/
}

void gtk_loopview_update_area(GtkLoopview *loopview, gint32 startx, gint32 endx){
	GdkRectangle update_rect;
	GtkWidget *widget = (GtkWidget*)loopview;
	guint32 i;
	gboolean docalc = FALSE;


	if (loopview->npeaks < 1) return;
	if (loopview->looperdata)
		if  (loopview->looperdata->buf) docalc = TRUE;

/*	printf ("update area: %d - %d\n",(int)startx, (int)endx);*/

	if (!loopview->fgc){
		loopview->bgc = gdk_gc_new (loopview->pixmap);
		loopview->fgc = gdk_gc_new (loopview->pixmap);
		gdk_gc_copy (loopview->fgc,widget->style->bg_gc[widget->state]);
		gdk_gc_copy (loopview->bgc,widget->style->bg_gc[widget->state]);
	}

	
	if (docalc){
		loopview->gridstart =
			((int)(loopview->zoomstart / loopview->gridwidth))
				* loopview->gridwidth;
		loopview->ggridstart = 
			gtk_loopview_sample2graphical(loopview, loopview->gridstart);
		loopview->ggridwidth = 
			(gdouble)(loopview->zoomend - loopview->zoomstart) / (gdouble)loopview->gridwidth;
/*
		loopview->ggridwidth = gtk_loopview_sample2graphical(loopview,
				loopview->zoomstart + loopview->gridwidth);
*/

		if (buffer_get_channels(loopview->looperdata->buf) > 1) {
			loopview->Lmid = loopview->height / 4;
			loopview->Rmid = loopview->height * 3 / 4;
			loopview->Hmax = (loopview->height / 4 ) - 2;
		}else{
			loopview->Lmid = loopview->height / 2;
			loopview->Hmax = (loopview->height / 2) - 2;
		}

		if (startx < 0) startx = 0;
		if (startx > loopview->npeaks) startx = loopview->npeaks;
		if (endx < 0) endx = 0;
		if (endx > loopview->npeaks) endx = loopview->npeaks;	

		if (startx > endx){
			gint32 tmp = endx;
			endx = startx;
			startx = tmp;
		}

		for (i = startx; i <= endx; i++){
			gtk_loopview_update_column(loopview, i);
			loopview->lastnup++;
		}
	
		/* middle line */
		if (buffer_get_channels(loopview->looperdata->buf) > 1)
			gdk_draw_line (loopview->pixmap,
				widget->style->fg_gc[widget->state],
				1,loopview->height / 2,
				loopview->width,loopview->height / 2);

/*		printf ("updated: %d - %d , %d\n",startx, endx, loopview->height);*/
	}else{
		gdk_gc_set_foreground(loopview->bgc,&loopview->bg_plain);
		gdk_draw_rectangle (loopview->pixmap,loopview->bgc,TRUE,
			startx,0,(endx - startx + 1),loopview->height);
/*		printf ("blanked: %d - %d , %d\n",startx, endx, loopview->height);*/
	}

	update_rect.x = startx;
	update_rect.y = 0;
	update_rect.height = loopview->height;
	update_rect.width = endx - startx + 1;
	gtk_widget_draw (GTK_WIDGET(loopview),&update_rect);
}

#if 0
void gtk_loopview_calc_peaks(GtkLoopview *loopview,guint32 startx, guint32 endx){
	float Lval;
	float Rval;
	float drift;
	gint8 *Lminp = NULL;
	gint8 *Rminp = NULL;
	gint8 *Lmaxp = NULL;
	gint8 *Rmaxp = NULL;
	guint64 i;
	guint64 j;
	guint64 steps;
	guint64 samples;
	guint64 peaks;

/*	printf ("calc peaks, ");
	printf ("height:%ld\n",(long)loopview->height);*/

	
	if (loopview->npeaks < 1) return;
	if  (loopview->looperdata == NULL){
		 gtk_loopview_update_area(loopview, startx, endx); 
		return;
	}
	if  (loopview->looperdata->buf == NULL){
		gtk_loopview_update_area(loopview, startx, endx);
		return;
	}

	drift = buffer_get_sampleratefactor(loopview->looperdata->buf,
				loopview->looperdata->samplerate);	

	if (endx > loopview->npeaks){endx = loopview->npeaks;}
	if (startx > endx){
		guint32 tmp = endx;
		endx = startx;
		startx = tmp;
	}
	peaks = endx - startx;

	if (loopview->npeaks > 0 && loopview->looperdata){
		if (loopview->looperdata->buf){
			samples = (guint32)(loopview->zoomend  - loopview->zoomstart);
			steps = (guint32)(samples / loopview->npeaks);
			Lminp = loopview->Lmin + startx;
			Lmaxp = loopview->Lmax + startx;
			if (buffer_get_channels(loopview->looperdata->buf) > 1){
				Rminp = loopview->Rmin + startx;
				Rmaxp = loopview->Rmax + startx;
			}
			for (i = 0; i < peaks; i++){
				*Lminp = 127; 
				*Lmaxp = -127;
				if (buffer_get_channels(loopview->looperdata->buf) > 1){
					*Rminp = 127;
					*Rmaxp = -127;
				}
				for (j = 0; j < steps; j++){
					float pos = loopview->zoomstart;
					pos += (startx + i) * (long)samples / (long)loopview->npeaks + j;
					pos *= drift;
					Lval = buffer_readsample_interpolated(loopview->looperdata->buf,1, 
								pos, loopview->buffer_group) * 127.;
					if ((gint8)Lval < *Lminp ){*Lminp = (gint8)Lval;}
					if ((gint8)Lval > *Lmaxp ){*Lmaxp = (gint8)Lval;}
					if (buffer_get_channels(loopview->looperdata->buf) > 1){
						Rval = buffer_readsample_interpolated(loopview->looperdata->buf,2, 
								pos, loopview->buffer_group) * 127.;
						if ((gint8)Rval < *Rminp ){*Rminp = (gint8)Rval;}
						if ((gint8)Rval > *Rmaxp ){*Rmaxp = (gint8)Rval;}
					}
				}

				Lminp++; Lmaxp++; 
				if (buffer_get_channels(loopview->looperdata->buf) > 1){
					Rminp++; Rmaxp++;
				}
			}	
/*			printf ("calc peaks update:i * j = %ld\n",(long)(i*j));*/
			gtk_loopview_update_area(loopview, startx, endx);
		}
	}
/*	printf ("calc peaks done\n");*/
}
#endif

void gtk_loopview_copy_peaks(GtkLoopview *loopview, peakdata_t *pd){
	long i;
	long len = pd->pend - pd->pstart;
/*	printf ("copy: %p. done:%d\n",pd,pd->done);*/
/*	printf ("copy: pstart:%ld, pend:%ld\n", pd->pstart, pd->pend);*/
	if (buffer_get_channels(loopview->looperdata->buf) > 1){
		for (i = 0; i < len;i++){
			*(loopview->Lmin + i + pd->pstart) = (gint8)*(pd->Lmin + i);
			*(loopview->Lmax + i + pd->pstart) = (gint8)*(pd->Lmax + i);
			*(loopview->Rmin + i + pd->pstart) = (gint8)*(pd->Rmin + i);
                	*(loopview->Rmax + i + pd->pstart) = (gint8)*(pd->Rmax + i);
		}
	} else {
		for (i = 0; i < len;i++){
			*(loopview->Lmin + i + pd->pstart) = (gint8)*(pd->Lmin + i);
                        *(loopview->Lmax + i + pd->pstart) = (gint8)*(pd->Lmax + i);	
		}
	}
	peakdata_set_status(pd,PD_STATUS_DEAD);
/*	printf ("updated:...%ld - %ld\n",pd->pstart, (pd->pstart + i));*/
	gtk_loopview_update_area(loopview, pd->pstart, pd->pend);
}

static gboolean gtk_loopview_expose( GtkWidget *widget, GdkEventExpose *event){
  	GtkLoopview *loopview = GTK_LOOPVIEW (widget);

/*	printf ("expose\n");*/

  	g_return_val_if_fail (widget != NULL, FALSE);
  	g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE);
  	g_return_val_if_fail (event != NULL, FALSE);

	if (event->count > 0) return FALSE;

	gdk_draw_drawable ((GdkDrawable*)widget->window,
			widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
			loopview->pixmap,
			event->area.x, event->area.y,
			event->area.x, event->area.y,
			event->area.width, event->area.height);

/*	printf ("expose done\n");*/
  	return FALSE;
}

/*
static gdouble gsnap2grid(GtkLoopview *loopview, gdouble x){
	gint diff;
	gint delta = 7;

	if (loopview->snap2grid == TRUE){
		diff = (gint)((x - loopview->ggridstart) / loopview->ggridwidth + .5) * loopview->ggridwidth;
		diff -= (x - loopview->ggridstart);

		if (abs(diff) < delta){
			x = loopview->ggridstart +
			 	((gint)((x - loopview->ggridstart) / loopview->ggridwidth) *
			 	loopview->ggridwidth);
		}
	}
	return x;
}
*/

static gdouble snap2grid(GtkLoopview *loopview, gdouble x){
	gdouble diff;
	gdouble delta;
	gdouble nearest;
	gint gdelta = 7;

	if (loopview->snap2grid == TRUE){
		/* equivalent of gdelta pixels */
                delta = gtk_loopview_graphical2sample(loopview, loopview->gloopstart + gdelta) -
                        gtk_loopview_graphical2sample(loopview, loopview->gloopstart); 
                nearest = (gint)((x - loopview->gridoffset) / loopview->gridwidth + .5) * loopview->gridwidth + loopview->gridoffset;
/*		nearest = (gint)(x / loopview->gridwidth + .5) * loopview->gridwidth; */
                diff = x - nearest;
		if (fabs(diff) < delta)	 x = nearest;
/*		printf ("x:%lf, nearest:%lf, diff:%lf, delta:%lf\n",
			(double)x,(double)nearest,(double)nearest,(double)delta);*/
	}
	return x;
}

static void gtk_loopview_set_loopstartend(GtkLoopview *loopview, gdouble temps, gdouble tempe){
/*
	printf ("%ld - %ld | %lf -  %lf\n",
		looperdata_get_loopstart(loopview->looperdata),looperdata_get_loopend(loopview->looperdata),temps,tempe);
*/
	if (temps < .0){temps = 0.;}
	if (temps > buffer_get_size(loopview->looperdata->buf)){
		temps = buffer_get_size(loopview->looperdata->buf);
	}
	if (tempe < .0){tempe = 0.;}
	if (tempe > buffer_get_size(loopview->looperdata->buf)){
		tempe = buffer_get_size(loopview->looperdata->buf);
	}
	if (temps > tempe){
		gdouble temp = temps;
		temps = tempe;
		tempe = temp;
	}
	looperdata_lock(loopview->looperdata);
	looperdata_set_loopstart(loopview->looperdata, temps);
	looperdata_set_loopend(loopview->looperdata, tempe);
	looperdata_unlock(loopview->looperdata);
}

static void gtk_loopview_set_recstartend(GtkLoopview *loopview, gdouble temps, gdouble tempe){
	if (temps < .0){temps = 0.;}
	if (temps > buffer_get_size(loopview->looperdata->buf)){
		temps = buffer_get_size(loopview->looperdata->buf);
	}
	if (tempe < .0){tempe = 0.;}
	if (tempe > buffer_get_size(loopview->looperdata->buf)){
		tempe = buffer_get_size(loopview->looperdata->buf);
	}
	if (temps > tempe){
		gdouble temp = temps;
		temps = tempe;
		tempe = temp;
	}
	looperdata_lock(loopview->looperdata);
	looperdata_set_recstart(loopview->looperdata, temps);
	looperdata_set_recend(loopview->looperdata, tempe);
	looperdata_unlock(loopview->looperdata);
}


static gboolean gtk_loopview_button_press( GtkWidget *widget,
		       GdkEventButton *origevent ){
	GdkEventButton *event = origevent;
	GtkLoopview *loopview;
	GdkCursor *cursor;
	gint maxd = 20;
	gint sdiff = 0;
	gint ediff = 0;
	gint bdiff = 0;
	gint t1, t2;

	g_return_val_if_fail (widget != NULL, FALSE);
	g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE);
	g_return_val_if_fail (event != NULL, FALSE);
	
	loopview = GTK_LOOPVIEW(widget);
	
	if (!loopview->looperdata) return FALSE;
	if (!loopview->looperdata->buf) return FALSE;

	loopview->button = event->button;

	if ((event->button == 1) && (event->state & GDK_CONTROL_MASK) && (event->state & GDK_MOD1_MASK)){
                if (loopview->looperdata->buf){
                        gettimeofday(&loopview->lastmousetime,0);
                        looperdata_lock(loopview->looperdata);
                        looperdata_set_playpos(loopview->looperdata,
				looperdata_get_loopstart(loopview->looperdata));
                        looperdata_unlock(loopview->looperdata);
                        t1 = loopview->gplaypos;
                        loopview->gplaypos = gtk_loopview_sample2graphical(loopview,
                                                looperdata_get_playpos(loopview->looperdata));
                        gtk_loopview_update_area(loopview,t1,t1);
                        gtk_loopview_update_area(loopview,loopview->gplaypos,loopview->gplaypos);
                        loopview->grabsel = 6 ; /* "scratch" with playhead */
                        loopview->speedbeforescratch = loopview->looperdata->speed;
                }
	} else if ((event->button == 1) && (event->state & GDK_CONTROL_MASK)){
		if (loopview->looperdata->buf){
			gettimeofday(&loopview->lastmousetime,0);
			looperdata_lock(loopview->looperdata);
			looperdata_set_playpos(loopview->looperdata,
				gtk_loopview_graphical2sample(loopview,event->x));
			/*
			loopview->looperdata->playpos = 
				gtk_loopview_graphical2sample(loopview,event->x);
			*/
			looperdata_unlock(loopview->looperdata);
			t1 = loopview->gplaypos;
                        loopview->gplaypos = gtk_loopview_sample2graphical(loopview,
                                                looperdata_get_playpos(loopview->looperdata));
                        gtk_loopview_update_area(loopview,t1,t1);
			gtk_loopview_update_area(loopview,loopview->gplaypos,loopview->gplaypos);
			loopview->grabsel = 6 ; /* "scratch" with playhead */
			loopview->speedbeforescratch = loopview->looperdata->speed;
		}
	} else if (event->button == 1){
		/* change selection */
		sdiff = loopview->gloopstart - event->x;
		ediff = event->x - loopview->gloopend;
		bdiff = loopview->gloopend - loopview->gloopstart;
		if (((sdiff < maxd) && (sdiff >= 0)) || 
			((sdiff <= 0) && (sdiff  > (maxd * -1) 
				&& (sdiff <(bdiff / 8 ))))){
			/* resize gloopstart */
			loopview->grabsel = 1; /* grab the start */
			cursor = gdk_cursor_new(GDK_LEFT_SIDE);
			gdk_window_set_cursor(widget->window,cursor);
		} else if (((ediff < maxd) && (ediff >= 0)) ||
			((ediff <= 0) && (ediff  > (maxd * -1)
				&& (sdiff <(bdiff / 8 ))))){
			/* resize gloopend */
			cursor = gdk_cursor_new(GDK_RIGHT_SIDE);
			gdk_window_set_cursor(widget->window,cursor);
			loopview->grabsel = 2; /* grab the end */
		} else if ((event->x > loopview->gloopstart) && (event->x <loopview->gloopend)){
			/* move and resize the whole selection */
			cursor = gdk_cursor_new(GDK_FLEUR);
			gdk_window_set_cursor(widget->window,cursor);
			if (event->state & GDK_SHIFT_MASK){	
				loopview->grabsel = 5; /* grab the whole loop, dont resize*/
			} else {
				loopview->grabsel = 3;/* grab the whole loop */
			}
			loopview->lastmouseX = event->x;
			loopview->lastmouseY = event->y;
		} else {
			/* new selection */
			t1 = loopview->gloopstart;
			t2 = loopview->gloopend;
			loopview->grabsel = 4;
			cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
			gdk_window_set_cursor(widget->window,cursor);

                       	gtk_loopview_set_loopstartend(loopview,
                       		snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x)),
				snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x)));
                      	loopview->gloopstart = gtk_loopview_sample2graphical(loopview,
                       				looperdata_get_loopstart(loopview->looperdata));
			loopview->gloopend = gtk_loopview_sample2graphical(loopview,
						looperdata_get_loopend(loopview->looperdata));

                        gtk_loopview_update_area(loopview,t1,t2);
		}
	} else if (event->button == 2){
		if (event->state & GDK_SHIFT_MASK){
			loopview->grabsel = 2;
		}else{
			loopview->grabsel = 1;
		}
		cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
		gdk_window_set_cursor(widget->window,cursor);
		loopview->gzoomstart = event->x;
		loopview->gzoomend = event->x;	
		loopview->lastmouseX = event->x;
		loopview->lastmouseY = event->y;
		gtk_widget_draw (GTK_WIDGET(loopview),NULL);

		/* LATER: menu for ctr-button:
		http://developer.gnome.org/doc/API/2.0/gtk/GtkMenu.html#gtk-menu-popup*/
	} else if ((event->button == 3) && (event->state & GDK_CONTROL_MASK) && (event->state & GDK_MOD1_MASK)){
                if (loopview->looperdata->buf){
                        looperdata_lock(loopview->looperdata);
                        /*looperdata_set_recpos(loopview->looperdata,
                                (double)gtk_loopview_graphical2sample(loopview,event->x));*/
			looperdata_set_recpos(loopview->looperdata,looperdata_get_recstart(loopview->looperdata));
                        looperdata_unlock(loopview->looperdata);
                }
	} else if ((event->button == 3) && (event->state & GDK_CONTROL_MASK)){
		if (loopview->looperdata->buf){
			looperdata_lock(loopview->looperdata);
			looperdata_set_recpos(loopview->looperdata, 
				(double)gtk_loopview_graphical2sample(loopview,event->x));
			looperdata_unlock(loopview->looperdata);
		}
	} else if (event->button == 3){
		sdiff = loopview->grecstart - event->x;
		ediff = event->x - loopview->grecend;
		bdiff = loopview->grecend - loopview->grecstart;

		/* change rec selection */
		if (((sdiff < maxd) && (sdiff > 0)) ||
			((sdiff < 0) && (sdiff  > (maxd * -1)
				&& (sdiff <(bdiff / 8 ))))){

			/* resize grecstart */
			loopview->grabsel = 1; /* grab the start */
			cursor = gdk_cursor_new(GDK_LEFT_SIDE);
			gdk_window_set_cursor(widget->window,cursor);
		}else if (((ediff < maxd) && (ediff > 0)) ||
			((ediff < 0) && (ediff  > (maxd * -1)
				&& (ediff <(bdiff / 8 ))))){
			/* resize grecend */
			cursor = gdk_cursor_new(GDK_RIGHT_SIDE);
			gdk_window_set_cursor(widget->window,cursor);
			loopview->grabsel = 2; /* grab the end */
		}else if ((event->x > loopview->grecstart) && (event->x <loopview->grecend)){
			/* move and resize the whole selection */
			cursor = gdk_cursor_new(GDK_FLEUR);
			gdk_window_set_cursor(widget->window,cursor);
			if (event->state & GDK_SHIFT_MASK){
				loopview->grabsel = 5; /* grab the whole loop,  dont resize*/
			}else{ 
				loopview->grabsel = 3;/* grab the whole loop */
			}
			loopview->lastmouseX = event->x;
			loopview->lastmouseY = event->y;
		}else{
			/* new selection */
                        t1 = loopview->grecstart;
                        t2 = loopview->grecend;
                        loopview->grabsel = 4;
                        cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
                        gdk_window_set_cursor(widget->window,cursor);

                        gtk_loopview_set_recstartend(loopview,
                                snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x)),
                                snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x) /*+ 1*/));
                        loopview->grecstart = gtk_loopview_sample2graphical(loopview,
                                                looperdata_get_recstart(loopview->looperdata));
                        loopview->grecend = gtk_loopview_sample2graphical(loopview,
                                                looperdata_get_recend(loopview->looperdata));

                        gtk_loopview_update_area(loopview,t1,t2);
		}
	}
	return FALSE;
}



static gboolean gtk_loopview_button_release( GtkWidget      *widget,
		       GdkEventButton *event )
{
	GtkLoopview *loopview;	
	GdkCursor *cursor;
	gdouble temps = 0.;
	gdouble tempe = 0.;
	gdouble temp = 0.;
	
	g_return_val_if_fail (widget != NULL, FALSE);
	g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE);
	g_return_val_if_fail (event != NULL, FALSE);

	loopview = GTK_LOOPVIEW(widget);

	if (!loopview->looperdata) return FALSE;
        if (!loopview->looperdata->buf) return FALSE;


/*	if (event->state & GDK_SHIFT_MASK){printf ("shift release\n");}*/

	if (loopview->button == event->button){
		if (loopview->button == 1){
			if ((loopview->grabsel == 6) && !(event->state & GDK_SHIFT_MASK)){
				/* restore original speed if shift is not pressed */
				looperdata_lock(loopview->looperdata);
				looperdata_set_speed(loopview->looperdata,loopview->speedbeforescratch);
				looperdata_unlock(loopview->looperdata);
				g_signal_emit(GTK_OBJECT(loopview),
					gtk_loopview_signals[SIG_SPEED_CHANGED],0);
			}
		} else	if (loopview->button == 2){
			/* zoom to new area if not at maximum already*/
			if (loopview->gzoomstart < 0 ){loopview->gzoomstart = 0;}
			if (loopview->gzoomend > loopview->npeaks){loopview->gzoomend = loopview->npeaks;}
			if (loopview->grabsel == 1){
				/* zoom in */
				temps = gtk_loopview_graphical2sample(loopview,loopview->gzoomstart);
				tempe = gtk_loopview_graphical2sample(loopview,loopview->gzoomend);
			}else if (loopview->grabsel == 2){
				/* shift was pressed: zoom out */
				temp = (gdouble)loopview->npeaks / (gdouble)(loopview->gzoomend - loopview->gzoomstart);
				loopview->gzoomstart = (loopview->npeaks - loopview->npeaks * temp ) / 2;
				loopview->gzoomend = loopview->npeaks + 
					(gint32)(loopview->npeaks * temp -loopview->npeaks ) / 2;	
				temps = gtk_loopview_graphical2sample(loopview,loopview->gzoomstart);
				tempe = gtk_loopview_graphical2sample(loopview,loopview->gzoomend);
/*				printf ("temps:%f, tempe:%f\n",(float)temps, (float)tempe);*/
				if (temps < 0){temps = 0;}
				if (loopview->looperdata->buf){
					if (tempe > buffer_get_size(loopview->looperdata->buf)){
						tempe = buffer_get_size(loopview->looperdata->buf);
					}
				}
			}
			if ((gint32)(tempe - temps) > loopview->npeaks){
				loopview->zoomstart = temps;
				loopview->zoomend = tempe;
				loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart);
				loopview->gloopend   = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend);
				loopview->grecstart  = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart);
				loopview->grecend    = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend);
/*				gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/
				if (!loopview->suspended)
					peakview_set_area(loopview->peakview,loopview->zoomstart, 
							loopview->zoomend, loopview->npeaks);
			}
			loopview->gzoomstart = 0;
			loopview->gzoomend = 0;
/*			gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/
			if (!loopview->suspended)
				peakview_calculate(loopview->peakview, loopview->zoomstart, loopview->zoomend);
/*			gtk_widget_draw (GTK_WIDGET(loopview),NULL);*/
		}

		cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
		gdk_window_set_cursor(widget->window,cursor);
/*		gtk_grab_remove (widget);*/
		loopview->button = 0;
		loopview->grabsel = 0;
		if (loopview->policy == GTK_UPDATE_DELAYED)	
			g_source_remove (loopview->timer);

	}		
	return FALSE;
}

static gboolean gtk_loopview_motion_notify( GtkWidget      *widget,
			GdkEventMotion *event )
{
	GtkLoopview *loopview;
	GdkModifierType mods;
	gint x, y, mask;
	gint maxd = 20;
	GdkCursor *cursor;

	g_return_val_if_fail (widget != NULL, FALSE);
	g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE);
	g_return_val_if_fail (event != NULL, FALSE);

	loopview = GTK_LOOPVIEW(widget);

	if (loopview->button){
		x = event->x;
		y = event->y;

		if (event->is_hint || (event->window != widget->window))
			gdk_window_get_pointer (widget->window, &x, &y, &mods);


		switch (loopview->button){
			case 1:
				mask = GDK_BUTTON1_MASK;
				break;
			case 2:
				mask = GDK_BUTTON2_MASK;
				break;
			case 3:
				mask = GDK_BUTTON3_MASK;
				break;
			default:
				mask = 0;
				break;
		}

		if (mods & mask)
			gtk_loopview_update_mouse (loopview,x,y);
	}else{
/*		printf ("motion notify x:%d, y:%d\n",(int)event->x,(int)event->y);*/
               	if ((loopview->pointerX != x) || (loopview->pointerY != y)){
			if (abs(event->x - loopview->gloopstart) < maxd){
				cursor = gdk_cursor_new(GDK_LEFT_SIDE);
				gdk_window_set_cursor(widget->window,cursor);
			}else if (abs(event->x - loopview->gloopend) < maxd){
				cursor = gdk_cursor_new(GDK_RIGHT_SIDE);
				gdk_window_set_cursor(widget->window,cursor);
			}else if ((event->x > loopview->gloopstart) && (event->x <loopview->gloopend)){
				cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
                                gdk_window_set_cursor(widget->window,cursor);
                        }else if (abs(event->x - loopview->grecstart) < maxd){
                                cursor = gdk_cursor_new(GDK_LEFT_SIDE);
                                gdk_window_set_cursor(widget->window,cursor);
                        }else if (abs(event->x - loopview->grecend) < maxd){
                                cursor = gdk_cursor_new(GDK_RIGHT_SIDE);
                                gdk_window_set_cursor(widget->window,cursor);
                        }else if ((event->x > loopview->grecstart) && (event->x <loopview->grecend)){
                                cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
                                gdk_window_set_cursor(widget->window,cursor);

			}else{
					cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
					gdk_window_set_cursor(widget->window,cursor);
			}
                        loopview->pointerX = event->x;
                        loopview->pointerY = event->y;
		}

	}

	return FALSE;
}

static void gtk_loopview_update_mouse (GtkLoopview *loopview, gint x, gint y)
{
	/*gint looplen;*/
	gint resize;
	gint tmp,t1,t2,t3,t4;
	suseconds_t tdiff;
/*	GdkRectangle update_rect;*/
	gdouble temp, diff;
	
  	g_return_if_fail (loopview != NULL);
  	g_return_if_fail (GTK_IS_LOOPVIEW (loopview));


	if (!loopview->looperdata) return;
	if (!loopview->looperdata->buf) return;

	if (loopview->button == 1){
		switch (loopview->grabsel){	
			case 1:
				tmp = loopview->gloopstart;
				gtk_loopview_set_loopstartend(loopview,
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)),
					looperdata_get_loopend(loopview->looperdata));
				loopview->gloopstart = gtk_loopview_sample2graphical(loopview,
								looperdata_get_loopstart(loopview->looperdata));
				gtk_loopview_update_area(loopview,tmp,loopview->gloopstart);
				break;
			case 2:
				tmp = loopview->gloopend;
				gtk_loopview_set_loopstartend(loopview,
					looperdata_get_loopstart(loopview->looperdata),
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)));
				loopview->gloopend = gtk_loopview_sample2graphical(loopview,
							looperdata_get_loopend(loopview->looperdata));
				gtk_loopview_update_area(loopview,tmp,loopview->gloopend);
				break;
			case 3:
				/*looplen = loopview->gloopend - loopview->gloopstart;*/
				resize = y - loopview->lastmouseY;
	
				t1 = loopview->gloopstart + 1 + x - loopview->lastmouseX - resize;
				/* should ifnd a better way to make the start really at 0 */
				if (loopview->gloopstart < 2) loopview->gloopstart = 0;
				t2 = loopview->gloopstart;
				t3 = loopview->gloopend + 1 + x - loopview->lastmouseX + resize;
				t4 = loopview->gloopend;

				gtk_loopview_set_loopstartend(loopview,
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t1)),
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t3)));

				loopview->gloopstart = gtk_loopview_sample2graphical(loopview,
							looperdata_get_loopstart(loopview->looperdata));
				loopview->gloopend = gtk_loopview_sample2graphical(loopview,
							looperdata_get_loopend(loopview->looperdata));
				
				gtk_loopview_update_area(loopview,loopview->gloopstart,t2);
				gtk_loopview_update_area(loopview,loopview->gloopend,t4);
				break;
			case 4:
				if ((abs(x - loopview->gloopend) >= abs(x - loopview->gloopstart)) 
					&& (x < loopview->gloopend)){
					tmp = loopview->gloopstart;
					gtk_loopview_set_loopstartend(loopview,
						snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)),
						looperdata_get_loopend(loopview->looperdata));
					loopview->gloopstart = gtk_loopview_sample2graphical(loopview,
									looperdata_get_loopstart(loopview->looperdata));
					gtk_loopview_update_area(loopview,tmp,loopview->gloopstart);
				}else{
					tmp = loopview->gloopend;
					gtk_loopview_set_loopstartend(loopview,
						looperdata_get_loopstart(loopview->looperdata),
						snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)));
					loopview->gloopend = gtk_loopview_sample2graphical(loopview,
								looperdata_get_loopend(loopview->looperdata));
					gtk_loopview_update_area(loopview,tmp,loopview->gloopend);
				}
				break;
			case 5:
                                t2 = loopview->gloopstart;
                                t4 = loopview->gloopend;

                                diff =  looperdata_get_loopend(loopview->looperdata)
                                        - looperdata_get_loopstart(loopview->looperdata);
                                temp = snap2grid(loopview,
                                        gtk_loopview_graphical2sample(loopview,
                                                loopview->gloopstart + 1 + x - loopview->lastmouseX));

                                gtk_loopview_set_loopstartend(loopview, temp, temp+diff);

                                loopview->gloopstart = gtk_loopview_sample2graphical(loopview,
                                        looperdata_get_loopstart(loopview->looperdata));
                                loopview->gloopend = gtk_loopview_sample2graphical(loopview,
                                        looperdata_get_loopend(loopview->looperdata));
                                gtk_loopview_update_area(loopview,loopview->gloopstart,t2);
                                gtk_loopview_update_area(loopview,loopview->gloopend,t4);
				break;
			case 6: 
				tdiff = loopview->lastmousetime.tv_usec;
				int xdiff = x - loopview->lastmouseX;
				gettimeofday(&loopview->lastmousetime,0);
				tdiff -= loopview->lastmousetime.tv_usec;
				loopview->lastmouseX = x;	
				temp = (double)(xdiff / (float)tdiff) * -1000.;
				if (fabs(temp)> .01){
					looperdata_lock(loopview->looperdata);
					loopview->looperdata->speed = 
						(double)(xdiff / (float)tdiff) * -1000.;
					looperdata_unlock(loopview->looperdata);
					g_signal_emit(GTK_OBJECT(loopview),
						gtk_loopview_signals[SIG_SPEED_CHANGED],0);
				}
				break;
			default:
/*				printf ("don't know what to do\n");*/
				break;
		}
		if (loopview->grabsel != 6){
			g_signal_emit(GTK_OBJECT(loopview),
					gtk_loopview_signals[SIG_LOOPBORDERS_CHANGED],0);
		}
	}else if (loopview->button == 2){
                if ((abs(x - loopview->gzoomend) >= abs(x - loopview->gzoomstart))
                		&& (x < loopview->gzoomend)){
			tmp = loopview->gzoomstart;
			loopview->gzoomstart = x;
			gtk_loopview_update_area(loopview,tmp,loopview->gzoomstart);
		}else{
			tmp = loopview->gzoomend;
			loopview->gzoomend = x;
			gtk_loopview_update_area(loopview,tmp,loopview->gzoomend);
		}
		g_signal_emit(GTK_OBJECT(loopview),
			gtk_loopview_signals[SIG_ZOOMBORDERS_CHANGED],0);
	}else if (loopview->button == 3){
		switch (loopview->grabsel){
			case 1:
				tmp = loopview->grecstart;
			       	gtk_loopview_set_recstartend(loopview,
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)),
					looperdata_get_recend(loopview->looperdata));
				loopview->grecstart = gtk_loopview_sample2graphical(loopview,
								looperdata_get_recstart(loopview->looperdata));
				gtk_loopview_update_area(loopview,tmp,loopview->grecstart);
				break;
			case 2:
				tmp = loopview->grecend;
				gtk_loopview_set_recstartend(loopview,
					looperdata_get_recstart(loopview->looperdata),
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)));
				loopview->grecend = gtk_loopview_sample2graphical(loopview,
								looperdata_get_recend(loopview->looperdata));
				gtk_loopview_update_area(loopview,tmp,loopview->grecend);
				break;
			case 3:
				/*looplen = loopview->grecend - loopview->grecstart;*/
				resize = y - loopview->lastmouseY;
							
				t1 = loopview->grecstart + 1 + x - loopview->lastmouseX - resize;
				t2 = loopview->grecstart;
				t3 = loopview->grecend + 1 + x - loopview->lastmouseX + resize;
				t4 = loopview->grecend;
			
				gtk_loopview_set_recstartend(loopview,
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t1)),
					snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t3)));
				
				loopview->grecstart = gtk_loopview_sample2graphical(loopview,
							looperdata_get_recstart(loopview->looperdata));
				loopview->grecend = gtk_loopview_sample2graphical(loopview,
							looperdata_get_recend(loopview->looperdata));
				gtk_loopview_update_area(loopview,loopview->grecstart,t2);
				gtk_loopview_update_area(loopview,loopview->grecend,t4);
				break;
			case 4:
                    if ((abs(x - loopview->grecend) >= abs(x - loopview->grecstart))
                                    	&& (x < loopview->grecend)){
					tmp = loopview->grecstart;
					gtk_loopview_set_recstartend(loopview,
						snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)),
						looperdata_get_recend(loopview->looperdata));
					loopview->grecstart = gtk_loopview_sample2graphical(loopview,
									looperdata_get_recstart(loopview->looperdata));
					gtk_loopview_update_area(loopview,tmp,loopview->grecstart);
				}else{
					tmp = loopview->grecend;
					gtk_loopview_set_recstartend(loopview,
						looperdata_get_recstart(loopview->looperdata),
						snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)));
					loopview->grecend = gtk_loopview_sample2graphical(loopview,
									looperdata_get_recend(loopview->looperdata));
					gtk_loopview_update_area(loopview,tmp,loopview->grecend);
				}
				break;
			case 5:
				t2 = loopview->grecstart;
				t4 = loopview->grecend;

				diff = 	looperdata_get_recend(loopview->looperdata)
					- looperdata_get_recstart(loopview->looperdata);
				temp = snap2grid(loopview,
					gtk_loopview_graphical2sample(loopview,
						loopview->grecstart + 1 + x - loopview->lastmouseX));

				gtk_loopview_set_recstartend(loopview,temp, temp+diff);

				loopview->grecstart = gtk_loopview_sample2graphical(loopview,
					looperdata_get_recstart(loopview->looperdata));
				loopview->grecend = gtk_loopview_sample2graphical(loopview,
					looperdata_get_recend(loopview->looperdata));
                                gtk_loopview_update_area(loopview,loopview->grecstart,t2);
                                gtk_loopview_update_area(loopview,loopview->grecend,t4);
				break;
			default:
/*				printf ("don't know what to do\n");*/
				break;
		}
		g_signal_emit(GTK_OBJECT(loopview),
					gtk_loopview_signals[SIG_RECBORDERS_CHANGED],0);


	}
	loopview->lastmouseX = x;
	loopview->lastmouseY = y;
}

static gint gtk_loopview_focus_in (GtkWidget * widget, GdkEventFocus * event){
	g_return_val_if_fail (widget != NULL,FALSE);
	g_return_val_if_fail (GTK_IS_LOOPVIEW (widget),FALSE);

/*	printf ("focus in\n");*/
  	GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
/*  	gtk_widget_draw_focus (widget);*/

  	return FALSE;
}

static gint gtk_loopview_focus_out (GtkWidget * widget, GdkEventFocus * event){
	g_return_val_if_fail (widget != NULL,FALSE);
	g_return_val_if_fail (GTK_IS_LOOPVIEW (widget),FALSE);

/*	printf ("focus out\n");*/
	GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
/*	gtk_widget_draw_focus (widget);*/

	return FALSE;
}

static gint gtk_loopview_enter_notify (GtkWidget *widget, GdkEventCrossing *event){
/*	printf ("enter\n");*/
  	gtk_widget_grab_focus (widget);
	gtk_grab_add (widget);
  	return TRUE;
}

static gint gtk_loopview_leave_notify  (GtkWidget *widget, GdkEventCrossing *event){
/*	printf ("leave\n");*/
	gtk_grab_remove(widget);
	return TRUE;
}

/*
static void gtk_loopview_update (GtkLoopview *loopview)
  	g_return_if_fail (loopview != NULL);
  	g_return_if_fail (GTK_IS_LOOPVIEW (loopview));

  	gtk_widget_draw (GTK_WIDGET(loopview), NULL);
}
*/

