/*
 * GQmpeg
 * (C)1998, 1999 John Ellis
 *
 * Author: John Ellis
 *
 * This software is released under the GNU General Public License.
 * Please read the included file COPYING for more information.
 * This software comes with no warranty of any kind, use at you own risk!
 */

#include "gqmpeg.h"

#define DIR_DEFAULT_HEIGHT 170

/*
 *-----------------------------------------------------------------------------
 * static vars
 *-----------------------------------------------------------------------------
 */

static GtkWidget *dirlist_clist;
static GtkWidget *filelist_clist;
static GtkWidget *playlist_clist;
static GtkWidget *pathentry;
static GtkWidget *historypulldown;
static GtkWidget *fileinfolabel;

/*
 *-----------------------------------------------------------------------------
 * static funcs
 *-----------------------------------------------------------------------------
 */

static void playlist_clist_construct_titles(gchar *titles[]);
static gchar *playlist_clist_column_data(SongData *data, gint column);
static void playlist_clist_arrange_data(gint pos, gchar *buf[]);
static gint playlist_clist_append(GtkCList *clist, gint pos);
static void playlist_clist_insert(GtkCList *clist, gint pos);
static void playlist_clist_update(GtkCList *clist, gint pos);
static gint playlist_sort_compare_func(gconstpointer a, gconstpointer b);
static void playlist_clist_column_clicked(GtkWidget *widget, gint column, gpointer data);

static void playlist_window_build();

/*
 *-----------------------------------------------------------------------------
 * Playlist population routines.
 * based on code by "Michael Bruun Petersen" <mbp@image.dk>
 *-----------------------------------------------------------------------------
 */
 
#define MAX_PLAYLIST_VIEW_ELEMENTS 10

static gint playlist_view_elements = 8;
static gint playlist_view_config[MAX_PLAYLIST_VIEW_ELEMENTS] = {1, 2, 3, 4, 5, 6, 7, 8, 0, 0};
static gint playlist_view_widths[MAX_PLAYLIST_VIEW_ELEMENTS] = {160, 100, 100, 30, 30, 60, 160 , 160, 0, 0};
static gchar* playlist_element_names[MAX_PLAYLIST_VIEW_ELEMENTS + 1] = 
	{"", "Title", "Album", "Artist", "Year", "Time", "Genre", "Filename", "Comment", "", ""};
static gint playlist_view_sort_column = -1;
static gint playlist_view_sort_invert = 0;

static void playlist_clist_construct_titles(gchar* titles[])
{
	gint i;
	for (i = 0; i < playlist_view_elements; i++)
		{
		titles[i] = playlist_element_names[playlist_view_config[i]];
		}
}

static gchar* playlist_clist_column_data(SongData* sd, gint column)
{
	static gchar *length_text = NULL;
	gint view;

	if (!sd || (column < 0) || (column >= playlist_view_elements))
		{
		return "";
		}

	view = playlist_view_config[column];
	switch (view)
		{
		case 1:
			if (sd->title)
				{
				return sd->title;
				}
			else
				{
				return filename_from_path(sd->path);
				}
		case 2:
			return sd->album;
		case 3:
			return sd->artist;
		case 4:
		        return sd->year;
		case 5:
			if (length_text) g_free(length_text);
			length_text = NULL;
			if (sd->live)
				{
				return "live";
				}
			else if (!sd->length)
				{
				return "";
				}
			else
				{
				length_text = g_strdup_printf("%0d:%02d", sd->length / 60, sd->length % 60);
				}
			return length_text;
		case 6:
			return sd->genre;
		case 7:
			return filename_from_path(sd->path);
		case 8:
			return sd->comment;
		default:
			return "";
		}
}

static void playlist_clist_arrange_data(gint pos, gchar *buf[])
{
        gint i;
	SongData *sd;

	sd = playlist_get_data(pos);

	if (!sd)
		{
		for (i = 0; i < playlist_view_elements; i++)
			{
			buf[i] = "";
			}
		return;
		}

	for (i = 0; i < playlist_view_elements; i++)
		{
		buf[i] = playlist_clist_column_data(sd, i);
		}
}

static gint playlist_clist_append(GtkCList *clist, gint pos)
{
	gchar *buf[MAX_PLAYLIST_VIEW_ELEMENTS];
	playlist_clist_arrange_data(pos, buf);
	return gtk_clist_append(clist, buf);
}

static void playlist_clist_insert(GtkCList *clist, gint pos)
{
	gchar *buf[MAX_PLAYLIST_VIEW_ELEMENTS];
	playlist_clist_arrange_data(pos, buf);
	gtk_clist_insert(clist, pos, buf);
}

static void playlist_clist_update(GtkCList *clist, gint pos)
{
	gchar *text;
	gint i;
	SongData *sd = playlist_get_data(pos);

	for (i = 0; i < playlist_view_elements; i++)
		{
		text = playlist_clist_column_data(sd, i);
		gtk_clist_set_text (clist, pos, i, text);
		}
}

static gint playlist_sort_compare_func(gconstpointer a, gconstpointer b)
{
	gint result;
	gchar *sa, *sb;

	if (playlist_view_config[playlist_view_sort_column] == 5) /* playlist_clist_column_data
					       returns static for this item */
		{
		gint al, bl;

		al = ((SongData*)a)->length;
		bl = ((SongData*)b)->length;

		if (al < bl)
			result = -1;
		else if (al > bl)
			result = 1;
		else
			result = 0;
		}
	else
		{
		sa = playlist_clist_column_data((SongData*) a, playlist_view_sort_column);
		sb = playlist_clist_column_data((SongData*) b, playlist_view_sort_column);
		if (!sa) sa = "";
		if (!sb) sb = "";

		result = strcasecmp(sa, sb);
		}

	if (playlist_view_sort_invert)
		return -result;
	else
		return result;
}

static void playlist_clist_column_clicked(GtkWidget *widget, gint column, gpointer data)
{
	gint i;
	gint l;
	GtkCList* clist = GTK_CLIST(widget);

	if (playlist_get_count() < 2) return;

	gtk_clist_freeze(clist);
	gtk_clist_clear(clist);

	if (column == playlist_view_sort_column)
		{
		playlist_view_sort_invert = 1 - playlist_view_sort_invert;
		}
	else
		{
		playlist_view_sort_column = column;
		playlist_view_sort_invert = 0;
		}

	playlist_sort_by_func((GCompareFunc) playlist_sort_compare_func);

	l = playlist_get_count();
	for (i = 0; i < l; i++)
		{
		playlist_clist_append(clist, i);
		}

	gtk_clist_thaw(clist);

	display_draw_song_number(current_song_get_number(), TRUE);
}

/*
 *-----------------------------------------------------------------------------
 * playlist window management functions (public)
 *-----------------------------------------------------------------------------
 */

void playlist_window_clist_append(gint n)
{
	if (!playlist_window) return;

	playlist_clist_append(GTK_CLIST(playlist_clist), n);
	playlist_window_length_update();
}

void playlist_window_clist_insert(gint n)
{
	if (!playlist_window) return;

	playlist_clist_insert(GTK_CLIST(playlist_clist), n);
	playlist_window_length_update();
}

void playlist_window_clist_move(gint s, gint t)
{
	if (!playlist_window || s == t) return;

	gtk_clist_row_move(GTK_CLIST(playlist_clist), s, t);
}

void playlist_window_clist_remove(gint n)
{
	if (!playlist_window) return;

	gtk_clist_remove(GTK_CLIST(playlist_clist), n);
	playlist_window_length_update();
}

void playlist_window_clist_update_item(gint n)
{
	if (!playlist_window) return;

	playlist_clist_update(GTK_CLIST(playlist_clist), n);
}

void playlist_window_clist_clear()
{
	if (!playlist_window) return;

	gtk_clist_clear(GTK_CLIST(playlist_clist));
	playlist_window_length_update();
}

void playlist_window_clist_populate()
{
	gint i;
	gint l;

	if (!playlist_window) return;

	gtk_clist_freeze (GTK_CLIST (playlist_clist));
	gtk_clist_clear (GTK_CLIST (playlist_clist));
	l = playlist_get_count();
	for (i=0; i < l; i++)
		{
		playlist_clist_append(GTK_CLIST(playlist_clist), i);
		}
	gtk_clist_thaw (GTK_CLIST (playlist_clist));
	playlist_window_length_update();
}

/*
 *-----------------------------------------------------------------------------
 * clist selection util functions (public)
 *-----------------------------------------------------------------------------
 */

gint clist_selection_count(GtkCList *clist)
{
	gint count = 0;
	GList *work = clist->selection;
	while(work)
		{
		count++;
		if (debug_mode) printf("s = %d\n", GPOINTER_TO_INT(work->data));
		work = work->next;
		}

	if (debug_mode) printf("selection = %d\n", count);

	return count;
}

gint clist_row_is_selected(GtkCList *clist, gint row)
{
	GList *work = clist->selection;

	while(work)
		{
		if (GPOINTER_TO_INT(work->data) == row) return TRUE;
		work = work->next;
		}

	return FALSE;
}

gint clist_selection_get_first_row(GtkCList *clist)
{
	GList *work = clist->selection;
	gint row = -1;

	while(work)
		{
		gint n = GPOINTER_TO_INT(work->data);
		if (n < row || row == -1)
			{
			row = n;
			}
		work = work->next;
		}

	return row;
}

GList *clist_selection_get_path_list(GtkCList *clist)
{
	GList *list = NULL;
	GList *work = clist->selection;

	while(work)
		{
		gchar *name = gtk_clist_get_row_data(clist, GPOINTER_TO_INT(work->data));
		list = g_list_append(list, g_strconcat(current_path, "/", name, NULL));
		work = work->next;
		}

	return list;
}

static gint playlist_selection_sort_cb(gconstpointer a, gconstpointer b)
{
	if (GPOINTER_TO_INT(a) < GPOINTER_TO_INT(b)) return -1;

	if (GPOINTER_TO_INT(a) > GPOINTER_TO_INT(b)) return 1;

	return 0;
}

GList *playlist_selection_get_number_list(gint sorted) /* don't free data pointers */
{
	GList *list = NULL;
	GList *work = GTK_CLIST(playlist_clist)->selection;

	while(work)
		{
		list = g_list_prepend(list, work->data);
		work = work->next;
		}

	if (sorted)
		{
		list = g_list_sort(list, (GCompareFunc) playlist_selection_sort_cb);
		}
	else
		{
		list = g_list_reverse(list);
		}

	return list;
}

GList *playlist_selection_get_path_list()
{
	GList *list = NULL;
	GList *work = GTK_CLIST(playlist_clist)->selection;

	while(work)
		{
		gchar *item = playlist_get_item(GPOINTER_TO_INT(work->data));
		list = g_list_append(list, g_strdup(item));
		work = work->next;
		}

	return list;
}

static GList *playlist_selection_get_only_file_list()
{
	GList *list = NULL;
	GList *work = GTK_CLIST(playlist_clist)->selection;

	while(work)
		{
		gchar *item = playlist_get_item(GPOINTER_TO_INT(work->data));
		if (isfile(item))
			{
			list = g_list_append(list, g_strdup(item));
			}
		work = work->next;
		}

	return list;
}

void free_selection_list(GList *list)
{
	g_list_foreach(list, (GFunc)g_free, NULL);
	g_list_free(list);
}

/*
 *-----------------------------------------------------------------------------
 * button press callbacks (private)
 *-----------------------------------------------------------------------------
 */

void update_list_highlight(GtkWidget *clistw, gint old, gint new, gint move)
{
	if (old >= 0)
		{
		gtk_clist_set_background(GTK_CLIST(clistw), old,
			&GTK_WIDGET (clistw)->style->base[GTK_STATE_NORMAL]);
		gtk_clist_set_foreground(GTK_CLIST(clistw), old,
			&GTK_WIDGET (clistw)->style->fg[GTK_STATE_NORMAL]);
		}
	if (new >= 0)
		{
		gtk_clist_set_background(GTK_CLIST(clistw), new,
			&GTK_WIDGET (clistw)->style->bg[GTK_STATE_SELECTED]);
		gtk_clist_set_foreground(GTK_CLIST(clistw), new,
			&GTK_WIDGET (clistw)->style->fg[GTK_STATE_SELECTED]);
		}
	if (move)
		{
		gtk_clist_moveto (GTK_CLIST(clistw), new, 0, 0.5, 0.0);
		}
}

/*
 *-----------------------------------------------------------------------------
 * button press callbacks (public)
 *-----------------------------------------------------------------------------
 */

static void add_dir_func(gint recursive)
{
	gchar *path;
	gint row = -1;
	row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(dirlist_clist)));
	path = dirlist_get_path(row);
	if (!path) return;
	playlist_append_from_dir(path, recursive);
	g_free(path);
}

static void save_pressed()
{
	if (playlist_pathname && isfile(playlist_pathname) && !playlist_get_count() < 1)
		{
		playlist_save(playlist_pathname);
		}
	else
		{
		playlist_dialog_save_as(playlist_pathname);
		}
}

static void save_as_pressed()
{
	playlist_dialog_save_as(playlist_pathname);
}

static void save_mode_changed(GtkWidget *w, gpointer data)
{
	save_mode_in_playlist = GTK_TOGGLE_BUTTON(w)->active;
}

void append_pressed()
{
	gchar *buf = g_strconcat(homedir(), "/", GQMPEG_RC_DIR_PLAYLIST, NULL);
	playlist_dialog_append(buf);
	g_free(buf);
}

void import_pressed()
{
	playlist_dialog_import(homedir());
}

static void change_dir_to_home()
{
	char *newdir;
	newdir = homedir();
	change_to_path(newdir);
}

static void add_all_button_pressed()
{
	gchar *path;
	gint i;
	gint count = filelist_count();
	if (count < 1) return;
	
	gtk_clist_freeze(GTK_CLIST(playlist_clist));
	for (i=0; i < count; i++)
		{
		path = filelist_get_path(i);
		if (!is_playlist(path))
			{
			playlist_add(path);
			}
		g_free(path);
		}
	gtk_clist_thaw(GTK_CLIST(playlist_clist));
}

static void remove_all_button_pressed()
{
	playlist_clear();
}

static void add_custom_pressed()
{
	playlist_dialog_add_custom_type(TRUE);
}

static void up_button_pressed()
{
	GList *list = playlist_selection_get_number_list(TRUE);
	GList *work;

	if (!list) return;

	work = list;
	if (GPOINTER_TO_INT(work->data == 0))
		{
		gint n = 0;
		while(work && GPOINTER_TO_INT(work->data) == n)
			{
			n++;
			work = work->next;
			}
		}
	while(work)
		{
		gint n = GPOINTER_TO_INT(work->data);
		playlist_move(n, n - 1);
		work = work->next;
		}

	g_list_free(list);
}

static void down_button_pressed()
{
	GList *list = playlist_selection_get_number_list(TRUE);
	GList *work;

	if (!list) return;

	work = g_list_last(list);
	if (GPOINTER_TO_INT(work->data) == playlist_get_count() - 1)
		{
		gint n = playlist_get_count() - 1;
		while(work && GPOINTER_TO_INT(work->data) == n)
			{
			n--;
			work = work->prev;
			}
		}
	while(work)
		{
		gint n = GPOINTER_TO_INT(work->data);
		playlist_move(n, n + 1);
		work = work->prev;
		}

	g_list_free(list);
}

static void top_button_pressed()
{
	GList *list = playlist_selection_get_number_list(TRUE);
	GList *work;
	gint row = 0;

	if (!list) return;

	work = list;
	while(work && GPOINTER_TO_INT(work->data) == row)
		{
		row++;
		work = work->next;
		}
	while(work)
		{
		gint n = GPOINTER_TO_INT(work->data);
		playlist_move(n, row);
		row++;
		work = work->next;
		}

	g_list_free(list);
}

static void end_button_pressed()
{
	GList *list = playlist_selection_get_number_list(TRUE);
	GList *work;
	gint row = playlist_get_count() - 1;

	if (!list) return;

	work = g_list_last(list);
	while(work && GPOINTER_TO_INT(work->data) == row)
		{
		row--;
		work = work->prev;
		}
	while(work)
		{
		gint n = GPOINTER_TO_INT(work->data);
		playlist_move(n, row);
		row--;
		work = work->prev;
		}

	g_list_free(list);
}

void pos_play_button_pressed()
{
}

/*
 *-----------------------------------------------------------------------------
 * menu dirlist press callbacks (public)
 *-----------------------------------------------------------------------------
 */

void plw_add_dir_pressed()
{
	add_dir_func(FALSE);
}

void plw_add_dir_recursive_pressed()
{
	add_dir_func(TRUE);
}

/*
 *-----------------------------------------------------------------------------
 * menu filelist press callbacks (public)
 *-----------------------------------------------------------------------------
 */

void plw_filelist_songinfo_pressed()
{
	gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(filelist_clist)));
	gchar *path = filelist_get_path(row);
	view_song_info(path);
	g_free(path);
}

void plw_filelist_move_pressed()
{
	GList *list = clist_selection_get_path_list(GTK_CLIST(filelist_clist));
	if (!list) return;

	if (!list->next)
		{
		file_util_move(list->data, NULL, current_path);
		g_list_free(list);
		}
	else
		{
		file_util_move(NULL, list, current_path);
		}
}

void plw_filelist_copy_pressed()
{
	GList *list = clist_selection_get_path_list(GTK_CLIST(filelist_clist));
	if (!list) return;

	if (!list->next)
		{
		file_util_copy(list->data, NULL, current_path);
		g_list_free(list);
		}
	else
		{
		file_util_copy(NULL, list, current_path);
		}
}

void plw_filelist_rename_pressed()
{
	GList *list = clist_selection_get_path_list(GTK_CLIST(filelist_clist));
	if (!list) return;

	if (!list->next)
		{
		file_util_rename(list->data, NULL);
		g_list_free(list);
		}
	else
		{
		file_util_rename(NULL, list);
		}
}

void plw_filelist_delete_pressed()
{
	GList *list = clist_selection_get_path_list(GTK_CLIST(filelist_clist));
	if (!list) return;

	if (!list->next)
		{
		file_util_delete(list->data, NULL);
		g_list_free(list);
		}
	else
		{
		file_util_delete(NULL, list);
		}
}

void plw_filelist_add_play_pressed()
{
	gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(filelist_clist)));
	gchar *path = filelist_get_path(row);
	playlist_add(path);
	g_free(path);
	current_song_set_and_play(playlist_get_count() - 1, NULL);
}

void plw_filelist_play_pressed()
{
	gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(filelist_clist)));
	gchar *path = filelist_get_path(row);
	current_song_set_and_play(-1, path);
	g_free(path);
}

void plw_filelist_add_pressed()
{
	GList *list = clist_selection_get_path_list(GTK_CLIST(filelist_clist));
	GList *work;

	if (!list) return;

	work = list;
	while(work)
		{
		gchar *path = work->data;
		if (!is_playlist(path))
			{
			playlist_add(path);
			}
		work = work->next;
		}

	free_selection_list(list);
}

void plw_filelist_insert_pressed()
{
	GList *list = clist_selection_get_path_list(GTK_CLIST(filelist_clist));
	GList *work;
	gint row;

	if (!list) return;

	row = clist_selection_get_first_row(GTK_CLIST(playlist_clist));

	if (row == -1) row = 0;

	work = list;
	while(work)
		{
		gchar *path = work->data;
		if (!is_playlist(path))
			{
			playlist_insert(path, row);
			row++;
			}
		work = work->next;
		}

	free_selection_list(list);
}

static void plw_load_or_append(gint append)
{
	gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(filelist_clist)));
	gchar *path = filelist_get_path(row);
	playlist_load_from_file(path, append, TRUE);
	g_free(path);
}

void plw_load_pressed()
{
	plw_load_or_append(FALSE);
}

void plw_append_pressed()
{
	plw_load_or_append(TRUE);
}

/*
 *-----------------------------------------------------------------------------
 * menu playlist press callbacks (public)
 *-----------------------------------------------------------------------------
 */

void plw_playlist_songinfo_pressed()
{
	gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(playlist_clist)));
	view_song_info(playlist_get_item(row));
}

void plw_playlist_edit_pressed()
{
	gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(playlist_clist)));
	playlist_dialog_edit_custom_type(playlist_get_data(row));
}

void plw_playlist_move_pressed()
{
	GList *list = playlist_selection_get_only_file_list();
	if (!list) return;

	if (!list->next)
		{
		file_util_move(list->data, NULL, current_path);
		g_list_free(list);
		}
	else
		{
		file_util_move(NULL, list, current_path);
		}
}

void plw_playlist_copy_pressed()
{
	GList *list = playlist_selection_get_only_file_list();
	if (!list) return;

	if (!list->next)
		{
		file_util_copy(list->data, NULL, current_path);
		g_list_free(list);
		}
	else
		{
		file_util_copy(NULL, list, current_path);
		}
}

void plw_playlist_rename_pressed()
{
	GList *list = playlist_selection_get_only_file_list();
	if (!list) return;

	if (!list->next)
		{
		file_util_rename(list->data, NULL);
		g_list_free(list);
		}
	else
		{
		file_util_rename(NULL, list);
		}
}

/* this _deletes files_ and removes items from the playlist */
void plw_playlist_delete_pressed()
{
	GList *list = playlist_selection_get_only_file_list();
	if (!list) return;

	if (!list->next)
		{
		file_util_delete(list->data, NULL);
		g_list_free(list);
		}
	else
		{
		file_util_delete(NULL, list);
		}
}

/* this only removes items from the playlist */
void plw_playlist_remove_pressed()
{
	GList *list = playlist_selection_get_number_list(TRUE);
	GList *work;

	if (!list) return;

	work = g_list_last(list);
	while(work)
		{
		playlist_remove(NULL, GPOINTER_TO_INT(work->data), FALSE);
		work = work->prev;
		}

	if (GPOINTER_TO_INT(list->data) < playlist_get_count())
		{
		gtk_clist_select_row(GTK_CLIST(playlist_clist), GPOINTER_TO_INT(list->data), 0);
		}
	else if (playlist_get_count() > 0)
		{
		gtk_clist_select_row(GTK_CLIST(playlist_clist), playlist_get_count() - 1, 0);
		}

	g_list_free(list);
}

void plw_playlist_play_pressed()
{
	gint row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(playlist_clist)));
	current_song_set_and_play(row, NULL);
}

/*
 *-----------------------------------------------------------------------------
 * dirlist callbacks
 *-----------------------------------------------------------------------------
 */

static void dirlist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
{
	gint row = -1;
	gint column = -1;
	if (bevent->window != GTK_CLIST(widget)->clist_window) return;

	gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &column);
	if (row == -1 || column == -1)
		{
		gtk_object_set_user_data(GTK_OBJECT(dirlist_clist), GINT_TO_POINTER(row));
		return;
		}

	if (bevent->button == 1 && bevent->type == GDK_2BUTTON_PRESS)
		{
		gchar *newdir = dirlist_get_path(row);
		change_to_path(newdir);
		g_free(newdir);
		}
	if (bevent->button == 2 || bevent->button == 3)
		{
		gtk_clist_select_row(GTK_CLIST(dirlist_clist), row, 0);
		gtk_object_set_user_data(GTK_OBJECT(dirlist_clist), GINT_TO_POINTER(row));
		}
	if (bevent->button == 3)
		{
		gtk_menu_popup (GTK_MENU(dir_menu), NULL, NULL, NULL, NULL,
				bevent->button, bevent->time);
		
		}
}

/*
 *-----------------------------------------------------------------------------
 * filelist callbacks
 *-----------------------------------------------------------------------------
 */

static void filelist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
{
	gint row = -1;
	gint column = -1;
	if (bevent->window != GTK_CLIST(widget)->clist_window) return;

	gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &column);
	if (row == -1 || column == -1) return;

	if (bevent->button == 1 && bevent->type == GDK_2BUTTON_PRESS)
		{
		gchar *newfile = filelist_get_path(row);
		playlist_add(newfile);
		g_free(newfile);
		}
	if (bevent->button == 2 || bevent->button == 3)
		{
		if (!clist_row_is_selected(GTK_CLIST(filelist_clist), row))
			{
			gtk_clist_unselect_all(GTK_CLIST(filelist_clist));
			gtk_clist_select_row(GTK_CLIST(filelist_clist), row, 0);
			}
		}
	if (bevent->button == 3)
		{
		gtk_object_set_user_data(GTK_OBJECT(filelist_clist), GINT_TO_POINTER(row));
		gtk_menu_popup (GTK_MENU(file_menu), NULL, NULL, NULL, NULL,
				bevent->button, bevent->time);
		}

}

/*
 *-----------------------------------------------------------------------------
 * playlist callbacks
 *-----------------------------------------------------------------------------
 */

static void playlist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
{
	gint row = -1;
	gint column = -1;
	if (bevent->window != GTK_CLIST(widget)->clist_window) return;

	gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &column);
	if (row == -1 || column == -1) return;

	if (debug_mode)	printf("%s\n", playlist_get_item(row));

	if (bevent->button == 1 && bevent->type == GDK_2BUTTON_PRESS)
		{
		current_song_set_and_play(row, NULL);
		}
	if (bevent->button == 2 || bevent->button == 3)
		{
		if (!clist_row_is_selected(GTK_CLIST(playlist_clist), row))
			{
			gtk_clist_unselect_all(GTK_CLIST(playlist_clist));
			gtk_clist_select_row(GTK_CLIST(playlist_clist), row, 0);
			}
		}
	if (bevent->button == 3)
		{
		gtk_object_set_user_data(GTK_OBJECT(playlist_clist), GINT_TO_POINTER(row));
		if (playlist_item_is_custom(row))
			{
			gtk_menu_popup (GTK_MENU(playlist_menu_custom), NULL, NULL, NULL, NULL,
				bevent->button, bevent->time);
			}
		else
			{
			gtk_menu_popup (GTK_MENU(playlist_menu), NULL, NULL, NULL, NULL,
				bevent->button, bevent->time);
			}
		}
}

/*
 *-----------------------------------------------------------------------------
 * history menu functions (private)
 *-----------------------------------------------------------------------------
 */

static void path_entry_select(gchar *newdir, gpointer data)
{
	if (isdir(newdir))
		{
		change_to_path(newdir);
		return;
		}
	else if (isfile(newdir))
		{
		gchar *buf;
		gchar *ptr;
		gchar *file;
		GList *list;

		buf = g_strdup(newdir);
		ptr = filename_from_path(buf);
		file = g_strdup(ptr);

		if (ptr > buf) ptr--;
		if (ptr == buf)
			{
			g_free(buf);
			buf = g_strdup("/");
			}
		else
			{
			ptr[0] = '\0';
			}
		if (strcmp(buf, current_path) != 0)
			{
			change_to_path(buf);
			}
		else
			{
			gtk_entry_set_text(GTK_ENTRY(pathentry), current_path);
			}

		list = filelist;
		while(list)
			{
			gchar *name = list->data;
			if (strcmp(name, file) == 0)
				{
				g_free(buf);
				buf = g_strconcat(current_path, "/", name, NULL);
				playlist_add(buf);
				g_free(buf);
				g_free(file);
				return;
				}
			list = list->next;
			}

                g_free(buf);
                g_free(file);
		}
}

static void history_menu_select(GtkWidget *widget, gchar *newdir)
{
	change_to_path(newdir);
}

static gchar *truncate_hist_text(gchar *t, gint l)
{
	gchar *tp;
	gchar *tbuf;
	if (l >= strlen(t)) return g_strdup(t);
	tp = t + strlen(t) - l;
	while (tp[0] != '/' && tp < t + strlen(t)) tp++;
		/* this checks to see if directory name is longer than l, if so */
		/* reset the length of name to l, it's better to have a partial */
		/* name than no name at all. */
	if (tp >= t + strlen(t)) tp = t + strlen(t) - l;
	tbuf = g_strconcat("/...", tp, NULL);
	return tbuf;
}

static void update_history_menu(gchar *path)
{
	static GList *history_list = NULL;
	GtkWidget *historymenu;
	GtkWidget *button;
	gchar *hist;
	gchar *hist_ptr;

	if (history_list)
		{
		g_list_foreach(history_list, (GFunc) g_free, NULL);
		g_list_free(history_list);
		history_list = NULL;
		}

	hist = g_strdup(path);
	hist_ptr = hist + strlen(hist) - 1 ;
	
	historymenu = gtk_menu_new();
	while (hist_ptr > hist)
		{
		gchar *path;
		gchar *hist_trunc;
		hist_trunc = truncate_hist_text(hist,32);
		button = gtk_menu_item_new_with_label (hist_trunc);
		g_free(hist_trunc);

		path = g_strdup(hist);
		history_list = g_list_append(history_list, path);
		gtk_signal_connect (GTK_OBJECT (button), "activate",
			(GtkSignalFunc) history_menu_select, path);

		gtk_menu_append (GTK_MENU (historymenu),button);
		gtk_widget_show (button);

		while (hist_ptr[0] != '/') hist_ptr--;
		hist_ptr[0] = '\0';
		}
	g_free(hist);
	/* looks like we have to add the root directory manually */
	button = gtk_menu_item_new_with_label ("/");

	gtk_signal_connect (GTK_OBJECT (button), "activate",
		(GtkSignalFunc) history_menu_select, "/");

	gtk_menu_append (GTK_MENU (historymenu), button);
	gtk_widget_show (button);

	gtk_option_menu_set_menu(GTK_OPTION_MENU(historypulldown), historymenu);
	gtk_entry_set_text(GTK_ENTRY(pathentry), path);
}

/*
 *-----------------------------------------------------------------------------
 * playlist misc functions (private)
 *-----------------------------------------------------------------------------
 */

void playlist_window_length_update()
{
	if (!playlist_window)
		{
		return;
		}
	else
		{
		gchar *buf;

		if (playlist_accounting)
			{
			gint hrs = playlist_get_length() / 3600;
			gint min = (playlist_get_length() - (hrs * 3600)) / 60;
			gint sec = playlist_get_length() - (hrs * 3600) - (min * 60);
			buf = g_strdup_printf("Playlist length: %02d:%02d:%02d , %d songs", hrs, min, sec, playlist_get_count());
			}
		else
			{
			buf = g_strdup_printf("(header loading is off), %d songs", playlist_get_count());
			}
		gtk_label_set(GTK_LABEL(fileinfolabel), buf);
		g_free(buf);
		}
}

void playlist_window_update_titles()
{
	gchar *buf;

	if (mainwindow)
		{
		buf = g_strconcat("GQmpeg - ", playlist_filename, NULL);
		gtk_window_set_title (GTK_WINDOW (mainwindow), buf);
		g_free(buf);
		}
	if (playlist_window)
		{
		buf = g_strconcat("GQmpeg playlist - ", playlist_filename, NULL);
		gtk_window_set_title (GTK_WINDOW (playlist_window), buf);
		g_free(buf);
		}
}

/*
 *-----------------------------------------------------------------------------
 * filelist update functions (private)
 *-----------------------------------------------------------------------------
 */

static void playlist_window_filelist_populate()
{
	GList *work;
	gchar *buf[2];
	gint row;

	buf[1] = NULL;

	gtk_clist_freeze (GTK_CLIST (dirlist_clist));
	gtk_clist_freeze (GTK_CLIST (filelist_clist));
	gtk_clist_clear (GTK_CLIST (dirlist_clist));
	gtk_clist_clear (GTK_CLIST (filelist_clist));

	work = dirlist;
	while(work)
		{
		buf[0] = work->data;
		row = gtk_clist_append(GTK_CLIST(dirlist_clist), buf);
		gtk_clist_set_row_data(GTK_CLIST(dirlist_clist), row, work->data);
		work = work->next;
		}
	
	work = filelist;
	while(work)
		{
		buf[0] = work->data;
		row = gtk_clist_append(GTK_CLIST(filelist_clist), buf);
		gtk_clist_set_row_data(GTK_CLIST(filelist_clist), row, work->data);
		work = work->next;
		}

	gtk_clist_thaw (GTK_CLIST (dirlist_clist));
	gtk_clist_thaw (GTK_CLIST (filelist_clist));

	update_history_menu(current_path);
}

void playlist_window_filelist_update()
{
	if (!playlist_window) return;

	playlist_window_filelist_populate();
}


/*
 *-----------------------------------------------------------------------------
 * playlist window drag and drop (private)
 *-----------------------------------------------------------------------------
 */

enum {
	TARGET_APP_PLAYLIST,
	TARGET_URI_LIST,
	TARGET_TEXT_PLAIN
};

static GtkTargetEntry filelist_drag_types[] = {
	{ "text/uri-list", 0, TARGET_URI_LIST },
	{ "text/plain", 0, TARGET_TEXT_PLAIN }
};
static gint filelist_drag_count = 2;

static GtkTargetEntry playlist_drag_types[] = {
	{ "application/x-gqmpeg-playlist", 0, TARGET_APP_PLAYLIST },
	{ "text/plain", 0, TARGET_TEXT_PLAIN }
};
static gint playlist_drag_count = 2;

static GtkTargetEntry playlist_drop_types[] = {
	{ "application/x-gqmpeg-playlist", 0, TARGET_APP_PLAYLIST },
	{ "text/uri-list", 0, TARGET_URI_LIST }
};
static gint playlist_drop_count = 2;

static void playlist_window_dirlist_set_dnd_data(GtkWidget *widget,
		GdkDragContext *context, GtkSelectionData *selection_data,
		guint info, guint time, gpointer data)
{
	gchar *uri_text = NULL;
	gint row = -1;
	gchar *name;

	row = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(dirlist_clist)));
	name = dirlist_get_path(row);

	if (!name) return;

	switch (info)
		{
		case TARGET_URI_LIST:
			uri_text = g_strconcat("file:", name, "\r\n", NULL);
			break;
		case TARGET_TEXT_PLAIN:
			uri_text = g_strconcat(name, "\n", NULL);
			break;
		default:
			break;
		}

	if (!uri_text) return;

	gtk_selection_data_set (selection_data, selection_data->target,
					8, uri_text, strlen(uri_text) + 1);
	g_free(uri_text);
	g_free(name);
}

static void playlist_window_filelist_set_dnd_data(GtkWidget *widget,
		GdkDragContext *context, GtkSelectionData *selection_data,
		guint info, guint time, gpointer data)
{
	GList *list;
	gchar *uri_text = NULL;
	gint uri_len = 0;

	list = clist_selection_get_path_list(GTK_CLIST(filelist_clist));
	if (!list) return;

	switch (info)
		{
		case TARGET_URI_LIST:
			uri_text = uri_create_text(list, &uri_len, FALSE);
			break;
		case TARGET_TEXT_PLAIN:
			uri_text = uri_create_text(list, &uri_len, TRUE);
			break;
		default:
			break;
		}

	free_selection_list(list);

	if (!uri_text) return;

	gtk_selection_data_set (selection_data, selection_data->target,
					8, uri_text, uri_len);
	g_free(uri_text);
}

static void playlist_window_playlist_set_dnd_data(GtkWidget *widget,
		GdkDragContext *context, GtkSelectionData *selection_data,
		guint info, guint time, gpointer data)
{
	GList *list;
	gchar *uri_text = NULL;
	gint uri_len = 0;

	if (clist_selection_count(GTK_CLIST(playlist_clist)) == 0) return;

	switch (info)
		{
		case TARGET_APP_PLAYLIST:
			uri_text = g_strdup("");
			uri_len = 1;
			break;
		case TARGET_TEXT_PLAIN:
			list = playlist_selection_get_path_list();
			if (!list) return;
			uri_text = uri_create_text(list, &uri_len, TRUE);
			free_selection_list(list);
			break;
		default:
			break;
		}

	if (!uri_text) return;

	gtk_selection_data_set (selection_data, selection_data->target,
					8, uri_text, uri_len);
	g_free(uri_text);
}

static void recalc_rows(GList *list, gint s, gint t)
{
	GList *work = list;

	while(work)
		{
		gint n = GPOINTER_TO_INT(work->data);
		if (s < n && n < t)
			{
			n--;
			}
		else if (s > n && n >= t)
			{
			n++;
			}
		work->data = GINT_TO_POINTER(n);
		work = work->next;
		}
}

static void playlist_window_playlist_get_dnd_data(GtkWidget *widget,
				GdkDragContext *context, gint x, gint y,
				GtkSelectionData *selection_data, guint info,
				guint time, gpointer data)
{
	gint row = -1;
	gint column = -1;
	gtk_clist_get_selection_info (GTK_CLIST(playlist_clist), x, y, &row, &column);
	row--; /* column titles are row 0 */

	if (debug_mode) printf("drop on %d\n", row);

	if (info == TARGET_URI_LIST)
		{
		GList *list = uri_get_list(selection_data->data);
		GList *work;

		if (!list) return;

		work = list;

		if (row < 0 || column == -1)
			{
			while(work)
				{
				gchar *name = work->data;
				if (isdir(name))
					{
					playlist_append_from_dir(name, FALSE);
					}
				else if (!is_playlist(name))
					{
					playlist_add(name);
					}
				work = work->next;
				}
			}
		else
			{
			while(work)
				{
				gchar *name = work->data;
				if (isdir(name))
					{
					playlist_append_from_dir(name, FALSE);
					}
				else if (!is_playlist(name))
					{
					playlist_insert(name, row);
					}
				row++;
				work = work->next;
				}
			}
		g_list_foreach(list, (GFunc)g_free, NULL);
		g_list_free(list);
		}
	if (info == TARGET_APP_PLAYLIST)
		{
		GList *list = playlist_selection_get_number_list(TRUE);
		GList *work;

		if (!list) return;
		if (clist_row_is_selected(GTK_CLIST(playlist_clist), row) ||
		    row < 0 || column == -1)
			{
			g_list_free(list);
			return;
			}

		work = list;
		while(work)
			{
			GList *t = work->next;
			gint n = GPOINTER_TO_INT(work->data);
			list = g_list_remove(list, work->data);
			playlist_move(n, row);
			recalc_rows(list, n, row);
			if (n > row) row++;
			work = t;
			}
		g_list_free(list);
		}
}

static void playlist_window_dnd_init()
{
	/* dir clist */
	gtk_drag_source_set(dirlist_clist, GDK_BUTTON2_MASK,
			filelist_drag_types, filelist_drag_count, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
	gtk_signal_connect(GTK_OBJECT(dirlist_clist), "drag_data_get",
			playlist_window_dirlist_set_dnd_data, NULL);

	/* file clist */
	gtk_drag_source_set(filelist_clist, GDK_BUTTON2_MASK,
			filelist_drag_types, filelist_drag_count, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
	gtk_signal_connect(GTK_OBJECT(filelist_clist), "drag_data_get",
			playlist_window_filelist_set_dnd_data, NULL);

	/* playlist clist */
	gtk_drag_dest_set(playlist_clist,
			GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, /* GTK_DEST_DEFAULT_HIGHLIGHT is out, flickers */
			playlist_drop_types, playlist_drop_count, 
			GDK_ACTION_COPY);
	gtk_signal_connect(GTK_OBJECT(playlist_clist), "drag_data_received",
			playlist_window_playlist_get_dnd_data , NULL);

	gtk_drag_source_set(playlist_clist, GDK_BUTTON2_MASK,
			playlist_drag_types, playlist_drag_count, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
	gtk_signal_connect(GTK_OBJECT(playlist_clist), "drag_data_get",
			playlist_window_playlist_set_dnd_data, NULL);
}

/*
 *-----------------------------------------------------------------------------
 * playlist window show / hide (public)
 *-----------------------------------------------------------------------------
 */

void playlist_window_show()
{
	if (playlist_window)
		{
		gdk_window_raise(playlist_window->window); 
		return;
		}

	playlist_window_build();
	playlist_window_filelist_populate();
	playlist_window_clist_populate();
}

void playlist_window_hide()
{
	if (!playlist_window) return;
	gdk_window_get_position (playlist_window->window, &window_list_x, &window_list_y);
	gdk_window_get_size(playlist_window->window, &window_list_w, &window_list_h);

	gtk_clist_clear(GTK_CLIST(dirlist_clist));
	gtk_clist_clear(GTK_CLIST(filelist_clist));
	gtk_widget_destroy(playlist_window);
	playlist_window = NULL;
}

static void playlist_window_build()
{
	GtkWidget *frame;
	GtkWidget *paned;
	GtkWidget *panedd;
	GtkWidget *hbox;
	GtkWidget *hbox1;
	GtkWidget *vbox;
	GtkWidget *vbox1;
	GtkWidget *vbox2;
	GtkWidget *button;
	GtkWidget *infopackbox;
	GtkWidget *scrolled;
	GtkWidget *tabcomp;

	gchar *dir_title [] = { "Directories:", };
	gchar *file_title [] = { "Files:", };
	gchar *play_title[MAX_PLAYLIST_VIEW_ELEMENTS];
	gchar *buf;
	gint i;

	/* set up playlist window */
	playlist_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_policy(GTK_WINDOW(playlist_window), TRUE, TRUE, FALSE);
	gtk_signal_connect (GTK_OBJECT (playlist_window), "delete_event",(GtkSignalFunc) playlist_window_hide, NULL);
	buf = g_strconcat("GQmpeg Playlist - ", playlist_filename, NULL);
	gtk_window_set_title (GTK_WINDOW (playlist_window), buf);
	g_free(buf);
	gtk_window_set_wmclass(GTK_WINDOW (playlist_window), "playlist", "GQmpeg");
	gtk_container_border_width (GTK_CONTAINER (playlist_window), 0);

	vbox = gtk_vbox_new (FALSE, 0);
	gtk_container_add (GTK_CONTAINER (playlist_window), vbox);
	gtk_widget_show (vbox);

	paned = gtk_hpaned_new();
	gtk_box_pack_start (GTK_BOX (vbox), paned, TRUE, TRUE, 0);
	gtk_widget_show (paned);

	hbox = gtk_hbox_new (FALSE, 0);
	gtk_paned_add1(GTK_PANED(paned), hbox);
	gtk_widget_show (hbox);

	vbox1 = gtk_vbox_new (FALSE, 0);
	gtk_box_pack_start (GTK_BOX (hbox), vbox1, TRUE, TRUE, 0);
	gtk_widget_show (vbox1);

	gtk_widget_realize(playlist_window);

        /* path entry */
        pathentry = gtk_entry_new_with_max_length(255);
	tabcomp = tab_completion_new(&pathentry, playlist_window, NULL, path_entry_select, NULL);
        gtk_box_pack_start (GTK_BOX (vbox1), tabcomp, FALSE, FALSE,0);
        gtk_widget_show (tabcomp);

	/* history button */
	historypulldown = gtk_option_menu_new ();
	gtk_box_pack_start (GTK_BOX (vbox1), historypulldown, FALSE, FALSE,0);
	gtk_widget_show (historypulldown);

	/* pane for dir-file lists */
	panedd = gtk_vpaned_new();
	gtk_paned_handle_size (GTK_PANED(panedd), 10);
        gtk_paned_gutter_size (GTK_PANED(panedd), 10);
	gtk_box_pack_start (GTK_BOX (vbox1), panedd, TRUE, TRUE, 0);
	gtk_widget_show (panedd);

	scrolled = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
				GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
	gtk_paned_add1(GTK_PANED(panedd), scrolled);
	gtk_widget_show(scrolled);

/*	gtk_paned_set_position(GTK_PANED(panedd), 170);*/

	/* directory list */
	dirlist_clist=gtk_clist_new_with_titles (1, dir_title);
	gtk_signal_connect (GTK_OBJECT (dirlist_clist), "button_press_event",(GtkSignalFunc) dirlist_press_cb, NULL);
	gtk_widget_set_usize (dirlist_clist, list_width, DIR_DEFAULT_HEIGHT);
	gtk_clist_column_titles_passive (GTK_CLIST (dirlist_clist)); 
	gtk_container_add (GTK_CONTAINER (scrolled), dirlist_clist);
	gtk_widget_show (dirlist_clist);

	scrolled = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
				GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
	gtk_paned_add2(GTK_PANED(panedd), scrolled);

	gtk_widget_show(scrolled);

	/* file list */
	filelist_clist=gtk_clist_new_with_titles (1, file_title);
	gtk_clist_set_selection_mode(GTK_CLIST(filelist_clist), GTK_SELECTION_EXTENDED);
	gtk_signal_connect (GTK_OBJECT (filelist_clist), "button_press_event",(GtkSignalFunc) filelist_press_cb, NULL);
	gtk_widget_set_usize (filelist_clist, list_width, -1);
	gtk_clist_column_titles_passive (GTK_CLIST (filelist_clist)); 
	gtk_container_add (GTK_CONTAINER (scrolled), filelist_clist);
	gtk_widget_show (filelist_clist);

	/* button vbox */

	vbox1 = gtk_vbox_new (FALSE, 0);
	gtk_container_border_width (GTK_CONTAINER (vbox1), 5);
	gtk_box_pack_start (GTK_BOX (hbox), vbox1, FALSE, FALSE, 0);
	gtk_widget_show (vbox1);

	hbox1 = gtk_hbox_new (TRUE, 5);
	gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 5);
	gtk_widget_show(hbox1);

	button = gtk_button_new_with_label("Home");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) change_dir_to_home, NULL);
	gtk_box_pack_start (GTK_BOX (hbox1), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Close");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) playlist_window_hide, NULL);
	gtk_box_pack_start (GTK_BOX (hbox1), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	frame = gtk_frame_new("Playlist");
	gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
	gtk_widget_show(frame);

	vbox2 = gtk_vbox_new (FALSE, 0);
	gtk_container_border_width (GTK_CONTAINER (vbox2), 5);
	gtk_container_add (GTK_CONTAINER (frame),vbox2);
	gtk_widget_show (vbox2);

	button = gtk_button_new_with_label("Save");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) save_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Save as...");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) save_as_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_check_button_new_with_label("save mode");
	gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), save_mode_in_playlist);
	gtk_signal_connect (GTK_OBJECT (button), "toggled",(GtkSignalFunc) save_mode_changed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Load");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) btn_load_playlist_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Append");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) append_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Import");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) import_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	frame = gtk_frame_new("Move Song");
	gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
	gtk_widget_show(frame);

	hbox1 = gtk_hbox_new (FALSE, 0);
	gtk_container_border_width (GTK_CONTAINER (hbox1), 5);
	gtk_container_add (GTK_CONTAINER (frame),hbox1);
	gtk_widget_show(hbox1);

	vbox2 = gtk_vbox_new (FALSE, 0);
	gtk_box_pack_start (GTK_BOX (hbox1), vbox2, TRUE, TRUE, 0);
	gtk_widget_show (vbox2);

	button = gtk_button_new_with_label("Top");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) top_button_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("End");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) end_button_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	vbox2 = gtk_vbox_new (FALSE, 0);
	gtk_box_pack_start (GTK_BOX (hbox1), vbox2, TRUE, TRUE, 0);
	gtk_widget_show (vbox2);

	button = gtk_button_new_with_label("Up");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) up_button_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Down");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) down_button_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	frame = gtk_frame_new("Songs");
	gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
	gtk_widget_show(frame);

	vbox2 = gtk_vbox_new (FALSE, 0);
	gtk_container_border_width (GTK_CONTAINER (vbox2), 5);
	gtk_container_add (GTK_CONTAINER (frame),vbox2);
	gtk_widget_show (vbox2);

	button = gtk_button_new_with_label("Add All");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) add_all_button_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Add");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) plw_filelist_add_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Insert");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) plw_filelist_insert_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Remove");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) plw_playlist_remove_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Remove All");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) remove_all_button_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	button = gtk_hseparator_new();
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 5);
	gtk_widget_show(button);

	button = gtk_button_new_with_label("Add Custom");
	gtk_signal_connect (GTK_OBJECT (button), "clicked",(GtkSignalFunc) add_custom_pressed, NULL);
	gtk_box_pack_start (GTK_BOX (vbox2), button, TRUE, TRUE, 0);
	gtk_widget_show(button);

	scrolled = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
				GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
	gtk_paned_add2(GTK_PANED(paned), scrolled);
	gtk_widget_show(scrolled);

	/* play list */
	playlist_clist_construct_titles(play_title);
	playlist_clist=gtk_clist_new_with_titles(playlist_view_elements, play_title);
	gtk_clist_set_selection_mode(GTK_CLIST(playlist_clist), GTK_SELECTION_EXTENDED);

	gtk_signal_connect (GTK_OBJECT (playlist_clist), "button_press_event",(GtkSignalFunc) playlist_press_cb, NULL);
	gtk_widget_set_usize (playlist_clist, list_width * 2, -1);
	for (i = 0; i < playlist_view_elements; i++)
		{
		gtk_clist_set_column_width(GTK_CLIST(playlist_clist), i, playlist_view_widths[i]);
		}
	gtk_signal_connect(GTK_OBJECT(playlist_clist), "click_column",
			   GTK_SIGNAL_FUNC(playlist_clist_column_clicked),
			   NULL);

	gtk_container_add (GTK_CONTAINER (scrolled), playlist_clist);
	gtk_widget_show (playlist_clist);

	/* create info pack box */
	infopackbox = gtk_hbox_new (FALSE, 0);
	gtk_box_pack_end (GTK_BOX (vbox), infopackbox, FALSE, FALSE, 0);
	gtk_widget_show (infopackbox);

	/* file info window */
	button = gtk_frame_new (NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(button),GTK_SHADOW_IN);
	gtk_box_pack_end (GTK_BOX (infopackbox), button, TRUE, TRUE, 0);
	gtk_widget_show (button);

	fileinfolabel = gtk_label_new ("");
	gtk_container_add (GTK_CONTAINER (button), fileinfolabel);
	gtk_widget_show (fileinfolabel);
	playlist_window_length_update();

	playlist_window_dnd_init();

	if (remember_window_position)
		{
		gtk_widget_set_usize(playlist_window, window_list_w, window_list_h);
/*		gtk_widget_set_uposition(playlist_window, window_list_x, window_list_y);
*/		}

	gtk_widget_show(playlist_window);

/*	if (remember_window_position)
		{
		gdk_window_move(playlist_window->window, window_list_x, window_list_y);
		}
*/
}

