/*
    This is gonna be my second "mod player" to date (previous one was in Turbo pascal + asm some 20years ago...)
    This one is intended to be a preview for underpowered platforms with lots of degrade functions (lower frequency, low bit count...)
*/

#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>

#include <string.h>

#include "player_module.h"
#include "alsa_playback.h"

GtkWidget *window;

GtkWidget *sample_drawing_area;
    
#define MY_MAX_PATH 4096

int cur_sample=1;
int cur_pattern=0;

void update_sample(void);

static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    g_print ("delete event occurred May autosave in release...\n");
    gtk_main_quit ();
}

static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}


/* open_file:
 *  Charge une nouvelle disquette (callback).
 */
static void open_mod_file ( GtkWidget *widget,
                     gpointer   data )
{
    GtkFileFilter *filter;
    static GtkWidget *dialog;
    char *folderName;
    static char folderNameLast[MY_MAX_PATH+1]="";
    char *fileName;

    g_print ("Open mod file...\n");

        dialog = gtk_file_chooser_dialog_new (
                 "Open a module file",
                 (GtkWindow *) window, GTK_FILE_CHOOSER_ACTION_OPEN,
                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
                 
        filter = gtk_file_filter_new ();
        gtk_file_filter_set_name (filter,"Plain old amiga files");
        gtk_file_filter_add_pattern (filter, "*.MOD");
        gtk_file_filter_add_pattern (filter, "*.mod");
        gtk_file_filter_add_pattern (filter, "mod.*");
        gtk_file_filter_add_pattern (filter, "MOD.*");
        gtk_file_chooser_add_filter ((GtkFileChooser *)dialog, filter);

        /* voids any pending message */
        while (gtk_events_pending ())
            gtk_main_iteration ();

    if (folderNameLast[0]=='\0') {
        strncpy(folderNameLast,g_get_current_dir(),MY_MAX_PATH);
    }
    
    (void)gtk_file_chooser_set_current_folder((GtkFileChooser *)dialog,folderNameLast);

    if (gtk_dialog_run ((GtkDialog *)dialog) == GTK_RESPONSE_ACCEPT)
    {
        fileName = gtk_file_chooser_get_filename((GtkFileChooser *)dialog);
        folderName = gtk_file_chooser_get_current_folder ((GtkFileChooser *)dialog);
        
        strncpy(folderNameLast,folderName,MY_MAX_PATH);
        load_module(fileName);
        update_song();
        update_pattern(0);
        update_sample(); 
    }
    
    gtk_widget_hide(dialog);
}

static void play_mod ( GtkWidget *widget,
                     gpointer   data )
{
	stop_playback();
	play_start();
	start_playback();
}

static void stop_mod ( GtkWidget *widget,
                     gpointer   data )
{
	stop_playback();
}

static void play_atstart ( GtkWidget *widget,
                     gpointer   data )
{
	stop_playback();
	play_start();
	start_playback();
}

static void play_rewind ( GtkWidget *widget,
                     gpointer   data )
{
	stop_playback();
	play_prev_pattern();
	start_playback();
}

static void play_forward ( GtkWidget *widget,
                     gpointer   data )
{
	stop_playback();
	play_next_pattern();
	start_playback();
}


void get_main_menu( GtkWidget  *window,
                    GtkWidget **menuBar
                     )
{
    GtkWidget *menu;
    GtkWidget *filemenu;
    GtkWidget *file;
    GtkWidget *new;
    GtkWidget *open;
    GtkWidget *export;
    GtkWidget *quit;

    GtkWidget *sep;

    GtkAccelGroup *accel_group = NULL;

    menu = gtk_menu_new ();
    
    *menuBar = gtk_menu_bar_new();
    filemenu = gtk_menu_new();

    accel_group = gtk_accel_group_new();
    gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);

    file = gtk_menu_item_new_with_mnemonic("_File");
//    new = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
    open = gtk_image_menu_item_new_from_stock("Open module", NULL);
    export = gtk_image_menu_item_new_from_stock("Export", NULL);
    sep = gtk_separator_menu_item_new();
    quit = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group);

    gtk_widget_add_accelerator(quit, "activate", accel_group, 
        GDK_KEY_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); 


    gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
//    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), new);
    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), open);
    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), export);
    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), sep);
    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
    gtk_menu_shell_append(GTK_MENU_SHELL(*menuBar), file);

    g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(gtk_main_quit), NULL);

    g_signal_connect(G_OBJECT(quit), "activate",
        G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(open), "activate",
        G_CALLBACK(open_mod_file),"from_menu");
        
}


void get_main_toolbar( GtkWidget  *window,
                    GtkWidget **toolBar
                     )
{
    GtkWidget *open;
    GtkWidget *export;
    GtkWidget *sep;
    GtkWidget *mediaStart;
    GtkWidget *mediaRewind;
    GtkWidget *mediaPlay;
    GtkWidget *mediaStop;
    GtkWidget *mediaForward;
    *toolBar = gtk_toolbar_new();
    gtk_toolbar_set_style(GTK_TOOLBAR(*toolBar), GTK_TOOLBAR_ICONS);

    gtk_container_set_border_width(GTK_CONTAINER(*toolBar), 2);

    open = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(open), -1);

    export = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(export), -1);
    
    sep = gtk_separator_tool_item_new();
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(sep), -1); 
    

    mediaStart = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PREVIOUS);
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(mediaStart), -1);


    mediaRewind = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_REWIND);
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(mediaRewind), -1);


    mediaPlay = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PLAY);
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(mediaPlay), -1);


    mediaStop = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_STOP);
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(mediaStop), -1);

    mediaForward = gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_FORWARD);
    gtk_toolbar_insert(GTK_TOOLBAR(*toolBar), GTK_TOOL_ITEM(mediaForward), -1);

    g_signal_connect(G_OBJECT(open), "clicked",
        G_CALLBACK(open_mod_file),"from_toolbar");

    g_signal_connect(G_OBJECT(mediaPlay), "clicked",
        G_CALLBACK(play_mod),"from_toolbar");

    g_signal_connect(G_OBJECT(mediaStop), "clicked",
        G_CALLBACK(stop_mod),"from_toolbar");

    g_signal_connect(G_OBJECT(mediaRewind), "clicked",
        G_CALLBACK(play_rewind),"from_toolbar");

    g_signal_connect(G_OBJECT(mediaForward), "clicked",
        G_CALLBACK(play_forward),"from_toolbar");

    g_signal_connect(G_OBJECT(mediaStart), "clicked",
        G_CALLBACK(play_atstart),"from_toolbar");
    
}


static	GtkWidget *song_view;
static	GtkListStore *list_store_song;

enum {
	SONG_INDEX=0,
	SONG_PATTERN,
	NB_COL
};

volatile int song_updating=FALSE;
gboolean
select_pattern (GtkTreeSelection *selection,
                     GtkTreeModel     *model,
                     GtkTreePath      *path,
                     gboolean          path_currently_selected,
                     gpointer          userdata)
{
	GtkTreeIter iter;
 
    if (gtk_tree_model_get_iter(model, &iter, path))
    {
		int song_pattern;
 
		gtk_tree_model_get(model, &iter, SONG_PATTERN, &song_pattern, -1);
 
		if (!path_currently_selected)
		{
			// g_print ("%d is going to be selected.\n", sample_index);
			cur_pattern=song_pattern;
			update_pattern(cur_pattern);
		}
		else
		{
			// g_print ("%s is going to be unselected.\n", name);
		}
 
	}
 
    return TRUE; /* allow selection state to change */
}

void
update_song_pos(int i) {
	GtkTreeSelection *selection;
	GtkTreePath *path;
	
	if (song_updating) return;
	
	selection=gtk_tree_view_get_selection(song_view);
	path=gtk_tree_path_new_from_indices(i,-1);
	gtk_tree_view_scroll_to_cell(song_view,path,NULL,FALSE,1.0,1.0);
	
	gtk_tree_selection_select_path(selection,path);
	
	gtk_tree_path_free(path);
	
}

void
update_song(void) {
	int loop;
	GtkTreeIter   iter;
	static	GtkListStore *list_store_song_new;

	song_updating=TRUE;
	
	list_store_song_new = gtk_list_store_new (2, G_TYPE_UINT, G_TYPE_UINT);	

	for (loop=0;loop<128;loop++) {
		gtk_list_store_append(list_store_song_new, &iter);

		gtk_list_store_set (list_store_song_new, &iter,
							SONG_INDEX, (guint)loop,
							SONG_PATTERN, (guint)get_song_pattern(loop),
							-1);	
	}

	gtk_tree_view_set_model(GTK_TREE_VIEW(song_view), GTK_TREE_MODEL(list_store_song_new));

	g_object_unref(list_store_song);
	
	list_store_song=list_store_song_new;
	song_updating=FALSE;
}

void get_song ( GtkWidget  *box
                     ) {
	GtkWidget *widget;
	GtkTreeViewColumn   *col;
	GtkCellRenderer     *renderer;
	GtkTreeIter   iter;
    GtkTreeSelection  *selection;
  
	int loop;

	list_store_song = gtk_list_store_new (2, G_TYPE_UINT, G_TYPE_UINT);	

	for (loop=0;loop<128;loop++) {
		gtk_list_store_append(list_store_song, &iter);

		gtk_list_store_set (list_store_song, &iter,
							SONG_INDEX, (guint)loop,
							SONG_PATTERN, (guint)0,
							-1);	
	}


	song_view = gtk_tree_view_new();	
	
	/* --- Column #1 --- */

	col = gtk_tree_view_column_new();	
	gtk_tree_view_column_set_title(col, "Num");

	gtk_tree_view_append_column(GTK_TREE_VIEW(song_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", SONG_INDEX);

	/* --- Column #2 --- */

	col = gtk_tree_view_column_new();

	gtk_tree_view_column_set_title(col, "Pattern");

	gtk_tree_view_append_column(GTK_TREE_VIEW(song_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", SONG_PATTERN);
               	
	
	gtk_tree_view_set_model(GTK_TREE_VIEW(song_view), GTK_TREE_MODEL(list_store_song));

	gtk_widget_show(song_view);

    widget=gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_min_content_height((GtkScrolledWindow*)widget,150);

    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
                                   GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

    gtk_container_add(GTK_CONTAINER(widget), song_view);
                                          
    gtk_box_pack_start( GTK_BOX(box), widget, TRUE, TRUE, 0);

	selection=gtk_tree_view_get_selection(song_view);
	gtk_tree_selection_set_select_function(selection, select_pattern, NULL, NULL);

}

static	GtkWidget *sample_view;
static	GtkListStore *list_store_sample;

enum {
	SAMPLE_INDEX=0,
	SAMPLE_NAME,
	SAMPLE_LEN,
	SAMPLE_HIT,
	SAMPLE_NOTES,
	NB_COL_SAMPLE
};

volatile int sample_updating=FALSE;

gboolean
select_sample (GtkTreeSelection *selection,
                     GtkTreeModel     *model,
                     GtkTreePath      *path,
                     gboolean          path_currently_selected,
                     gpointer          userdata)
{
	GtkTreeIter iter;
 
    if (gtk_tree_model_get_iter(model, &iter, path))
    {
		int sample_index;
 
		gtk_tree_model_get(model, &iter, SAMPLE_INDEX, &sample_index, -1);
 
		if (!path_currently_selected)
		{
			// g_print ("%d is going to be selected.\n", sample_index);
			cur_sample=sample_index;
			gtk_widget_queue_draw(sample_drawing_area);
		}
		else
		{
			// g_print ("%s is going to be unselected.\n", name);
		}
 
	}
 
    return TRUE; /* allow selection state to change */
}

void
update_sample(void) {
	int loop;
	GtkTreeIter   iter;
	static	GtkListStore *list_store_sample_new;

	sample_updating=TRUE;
	
	list_store_sample_new = gtk_list_store_new (5, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);	

	for (loop=1;loop<get_nb_sample()+1;loop++) {
		gtk_list_store_append(list_store_sample_new, &iter);

		gtk_list_store_set (list_store_sample_new, &iter,
							SAMPLE_INDEX, (guint)loop,
							SAMPLE_NAME, (guint)get_sample_name(loop),
							SAMPLE_LEN, (guint)get_sample_size(loop),
							SAMPLE_HIT, (guint)get_sample_hit(loop),
							SAMPLE_NOTES, (guint)get_sample_pitch_hit(loop),
							-1);	
	}

	gtk_tree_view_set_model(GTK_TREE_VIEW(sample_view), GTK_TREE_MODEL(list_store_sample_new));

	g_object_unref(list_store_sample);
	
	list_store_sample=list_store_sample_new;
	sample_updating=FALSE;
}

void get_sample ( GtkWidget  *box
                     ) {
	GtkWidget *widget;
	GtkTreeViewColumn   *col;
	GtkCellRenderer     *renderer;
	GtkTreeIter   iter;
    GtkTreeSelection  *selection;
      
	int loop;

	list_store_sample = gtk_list_store_new (5, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);	

	for (loop=1;loop<32;loop++) {
		gtk_list_store_append(list_store_sample, &iter);

		gtk_list_store_set (list_store_sample, &iter,
							SAMPLE_INDEX, (guint)loop,
							SAMPLE_NAME, "",
							SAMPLE_LEN, 0,
							SAMPLE_HIT, 0,
							SAMPLE_NOTES, 0,
							-1);	
	}


	sample_view = gtk_tree_view_new();	
	
	/* --- Column #1 --- */

	col = gtk_tree_view_column_new();	
	gtk_tree_view_column_set_title(col, "Num");

	gtk_tree_view_append_column(GTK_TREE_VIEW(sample_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", SAMPLE_INDEX);

	/* --- Column #2 --- */

	col = gtk_tree_view_column_new();

	gtk_tree_view_column_set_title(col, "Sample");

	gtk_tree_view_append_column(GTK_TREE_VIEW(sample_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", SAMPLE_NAME);

	/* --- Column #3 --- */

	col = gtk_tree_view_column_new();

	gtk_tree_view_column_set_title(col, "Length");

	gtk_tree_view_append_column(GTK_TREE_VIEW(sample_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", SAMPLE_LEN);

	/* --- Column #4 --- */

	col = gtk_tree_view_column_new();

	gtk_tree_view_column_set_title(col, "Used");

	gtk_tree_view_append_column(GTK_TREE_VIEW(sample_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", SAMPLE_HIT);

	/* --- Column #5 --- */

	col = gtk_tree_view_column_new();

	gtk_tree_view_column_set_title(col, "Notes");

	gtk_tree_view_append_column(GTK_TREE_VIEW(sample_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", SAMPLE_NOTES);
               	
	
	gtk_tree_view_set_model(GTK_TREE_VIEW(sample_view), GTK_TREE_MODEL(list_store_sample));

	gtk_widget_show(sample_view);

    widget=gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_min_content_height((GtkScrolledWindow*)widget,150);

    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
                                   GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

    gtk_container_add(GTK_CONTAINER(widget), sample_view);
                                          
    gtk_box_pack_start( GTK_BOX(box), widget, TRUE, TRUE, 0);

	selection=gtk_tree_view_get_selection(sample_view);
	gtk_tree_selection_set_select_function(selection, select_sample, NULL, NULL);

}


void get_main_upper_panel ( GtkWidget  *window,
                    GtkWidget **upperPanel
                     ) {
    GtkWidget *songBox;
    GtkWidget *dialogBox;
    GtkWidget *voicesBox;
    GtkWidget *mixBox;
	GtkWidget *sampleBox;
	
    GtkWidget *separator;
	
    *upperPanel=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
    
    songBox=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
    gtk_box_pack_start( GTK_BOX(*upperPanel), songBox, FALSE, FALSE, 0);

	get_song(songBox);

    separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
    gtk_box_pack_start( GTK_BOX(*upperPanel), separator, FALSE, FALSE, 0);
        
    dialogBox=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
    gtk_box_pack_start( GTK_BOX(*upperPanel), dialogBox, FALSE, FALSE, 0);

    separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
    gtk_box_pack_start( GTK_BOX(*upperPanel), separator, FALSE, FALSE, 0);

    voicesBox=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
    gtk_box_pack_start( GTK_BOX(*upperPanel), voicesBox, FALSE, FALSE, 0);

    separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
    gtk_box_pack_start( GTK_BOX(*upperPanel), separator, FALSE, FALSE, 0);

    mixBox=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
    gtk_box_pack_start( GTK_BOX(*upperPanel), mixBox, FALSE, FALSE, 0);

    separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
    gtk_box_pack_start( GTK_BOX(*upperPanel), separator, FALSE, FALSE, 0);

    sampleBox=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
    gtk_box_pack_start( GTK_BOX(*upperPanel), sampleBox, FALSE, FALSE, 0);

	get_sample(sampleBox);
	
}

static GtkWidget *pattern_text_view;
static GtkTextBuffer *pattern_text_buffer;

static	GtkWidget *pattern_view;
static	GtkListStore *list_store_pattern;

enum {
	PATTERN_INDEX=0,
	PATTERN_CONTENT,
	NB_COL_PATTERN
};

volatile int pattern_updating=FALSE;

void
update_pattern_pos(int i) {
	GtkTreeSelection *selection;
	GtkTreePath *path;
	
	if (pattern_updating) return;
	selection=gtk_tree_view_get_selection(pattern_view);
	path=gtk_tree_path_new_from_indices(i,-1);
	
	gtk_tree_selection_select_path(selection,path);
	gtk_tree_view_scroll_to_cell(pattern_view,path,NULL,FALSE,1.0,1.0);
	gtk_tree_path_free(path);
}


void
update_pattern(int patnum) {
	int loop;
	GtkTreeIter   iter;
	static	GtkListStore *list_store_pattern_new;
	
	pattern_updating=TRUE;
	
	list_store_pattern_new = gtk_list_store_new (2, G_TYPE_UINT, G_TYPE_STRING);	

	for (loop=0;loop<64;loop++) {
		gtk_list_store_append(list_store_pattern_new, &iter);

		gtk_list_store_set (list_store_pattern_new, &iter,
							PATTERN_INDEX, (guint)loop,
							PATTERN_CONTENT, get_pattern_line(patnum,loop),
							-1);	
	}

	gtk_tree_view_set_model(GTK_TREE_VIEW(pattern_view), GTK_TREE_MODEL(list_store_pattern_new));

	g_object_unref(list_store_pattern);
	
	list_store_pattern=list_store_pattern_new;
	pattern_updating=FALSE;
}

void get_pattern ( GtkWidget  *box
                     ) {
	GtkWidget *widget;
	GtkTreeViewColumn   *col;
	GtkCellRenderer     *renderer;
	GtkTreeIter   iter;
  
	int loop;

	list_store_pattern = gtk_list_store_new (2, G_TYPE_UINT, G_TYPE_STRING);	

	for (loop=0;loop<64;loop++) {
		gtk_list_store_append(list_store_pattern, &iter);

		gtk_list_store_set (list_store_pattern, &iter,
							PATTERN_INDEX, (guint)loop,
							PATTERN_CONTENT, get_pattern_line(0,loop),
							-1);	
	}

	pattern_view = gtk_tree_view_new();	
	
	/* --- Column #1 --- */

	col = gtk_tree_view_column_new();	
	gtk_tree_view_column_set_title(col, "Num");

	gtk_tree_view_append_column(GTK_TREE_VIEW(pattern_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", PATTERN_INDEX);

	/* --- Column #2 --- */

	col = gtk_tree_view_column_new();

	gtk_tree_view_column_set_title(col, "Pattern");

	gtk_tree_view_append_column(GTK_TREE_VIEW(pattern_view), col);

	renderer = gtk_cell_renderer_text_new();

	/* pack cell renderer into tree view column */
	gtk_tree_view_column_pack_start(col, renderer, TRUE);
	gtk_tree_view_column_add_attribute(col, renderer, "text", PATTERN_CONTENT);
    g_object_set(renderer,
               "family", "Monospace",
               "cell-family-set", TRUE,
               NULL);              	
	
	gtk_tree_view_set_model(GTK_TREE_VIEW(pattern_view), GTK_TREE_MODEL(list_store_pattern));

	gtk_widget_show(pattern_view);

    widget=gtk_scrolled_window_new (NULL, NULL);

    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
                                   GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

    gtk_container_add(GTK_CONTAINER(widget), pattern_view);
    gtk_box_pack_start( GTK_BOX(box), widget, TRUE, TRUE, 0);
    
}

gboolean
sample_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data) {
	guint width, height;
	GdkRGBA color;
	float *tab;
	int loop;

	width = gtk_widget_get_allocated_width (widget);
	height = gtk_widget_get_allocated_height (widget);
  
	tab=get_sample_preview(cur_sample,width,4);
	if (tab==NULL) return FALSE;
	
	cairo_set_line_width (cr, .5);
	cairo_set_source_rgb(cr, 1, 0, 0);
	
	cairo_move_to(cr,0*1.0,(height*(tab[0]+1.0))/2.0);
	for (loop=1;loop<width;loop++) {
		cairo_line_to(cr,loop*1.0,(height*(tab[loop]+1.0))/2.0);
	}
	cairo_stroke(cr);
	

	return FALSE;
}

void get_main_lower_panel ( GtkWidget  *window,
                    GtkWidget **lowerPanel
                     ) {
	GtkWidget *notebook;
    GtkWidget *frame;
    GtkWidget *widget;
    GtkWidget *pattern;
    GtkWidget *content;

    
    *lowerPanel = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
    notebook=gtk_notebook_new();
    gtk_box_pack_start( GTK_BOX(*lowerPanel), notebook, TRUE, TRUE, 0);

	/* the pattern panel */
    frame=gtk_frame_new("");
    gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_NONE);
    gtk_frame_set_label_align( GTK_FRAME(frame), 0.985, 0.0);
    widget=gtk_label_new("Pattern");
    gtk_notebook_append_page( GTK_NOTEBOOK(notebook), frame, widget);

    content=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add( GTK_CONTAINER(frame), content);

	get_pattern(content);

	/* the sample panel */
    frame=gtk_frame_new("");
    gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_NONE);
    gtk_frame_set_label_align( GTK_FRAME(frame), 0.985, 0.0);
    widget=gtk_label_new("Sample");
    gtk_notebook_append_page( GTK_NOTEBOOK(notebook), frame, widget);

    content=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add( GTK_CONTAINER(frame), content);

	/* for now just the cairo drawing area */
	sample_drawing_area = gtk_drawing_area_new ();
	gtk_widget_set_size_request (sample_drawing_area, 50, 50);
	g_signal_connect (G_OBJECT (sample_drawing_area), "draw",
                    G_CALLBACK (sample_draw_callback), NULL);

    gtk_box_pack_start( GTK_BOX(content), sample_drawing_area, TRUE, TRUE, 0);
	
}

static gint timer = 0;
volatile int timer_updating=FALSE;

/*
 * do update in a non blocking timer to avoid conflicts with gtk_main() 
 */
gint TimerCallback (gpointer data)
{
	static int old_song_pos=-1,song_pos;
	static int old_patnum=-1,patnum;
	static int old_note=-1,note;

	if (timer_updating) return;
	
	timer_updating=TRUE;

	where_am_i(&song_pos,&patnum,&note);
	if (old_patnum!=patnum) {
		    update_pattern(patnum);
			old_patnum=patnum;
	}
	if (old_note!=note) {
		    update_pattern_pos(note);
			old_note=note;
	}
	if (old_song_pos!=song_pos) {
		    update_song_pos(song_pos);
			old_song_pos=song_pos;
	}
	timer_updating=FALSE;
	
    return 1; // NOTE: Needs to be non-zero otherwise timer will stop
}

int main( int   argc,
          char *argv[] )
{
    GtkWidget *button;
    GtkWidget *mainVbox;
    GtkWidget *menuBar;
    GtkWidget *toolBar;
    GtkWidget *upperPanel;
    GtkWidget *lowerPanel;
  
    gtk_init (&argc, &argv);
    

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 600, 400);
    gtk_window_set_title(GTK_WINDOW(window), "VitalMotion min tracker");
    
    g_signal_connect (window, "delete-event",
		      G_CALLBACK (delete_event), NULL);
    
    g_signal_connect (window, "destroy",
		      G_CALLBACK (destroy), NULL);
        
    mainVbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
    gtk_container_add (GTK_CONTAINER (window), mainVbox);
    gtk_widget_show (mainVbox);
  
    get_main_menu (window, &menuBar);
    gtk_box_pack_start (GTK_BOX (mainVbox), menuBar, FALSE, TRUE, 0);
 
    get_main_toolbar (window, &toolBar);
    gtk_box_pack_start (GTK_BOX (mainVbox), toolBar, FALSE, TRUE, 0);

    get_main_upper_panel (window, &upperPanel);
    gtk_box_pack_start (GTK_BOX (mainVbox), upperPanel, FALSE, TRUE, 0);

    get_main_lower_panel (window, &lowerPanel);
    gtk_box_pack_start (GTK_BOX (mainVbox), lowerPanel, TRUE, TRUE, 0);
 
    gtk_widget_show_all (window);
    
    update_song();
    
    timer = g_timeout_add (10, TimerCallback, NULL);
                
    gtk_main ();
    
    return 0;
}

