diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-11-11 20:33:51 +0100 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-11-11 20:33:51 +0100 |
commit | 526cbb98cf3f38657afc75ba9e468e3d9dd5232f (patch) | |
tree | 970e3bb1394379805758d3da6bc02369306eaa42 /plugins | |
parent | 69e0ddb79f353cbf67cbf8db9517e2e71ed87d5c (diff) |
created gtkui plugin, started moving stuff out
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/gtkui/Makefile.am | 15 | ||||
-rw-r--r-- | plugins/gtkui/callbacks.c | 1763 | ||||
-rw-r--r-- | plugins/gtkui/callbacks.h | 694 | ||||
-rw-r--r-- | plugins/gtkui/deadbeef.glade | 2493 | ||||
-rw-r--r-- | plugins/gtkui/deadbeef.gladep | 10 | ||||
-rw-r--r-- | plugins/gtkui/drawing.h | 74 | ||||
-rw-r--r-- | plugins/gtkui/gdkdrawing.c | 150 | ||||
-rw-r--r-- | plugins/gtkui/gtkplaylist.c | 2038 | ||||
-rw-r--r-- | plugins/gtkui/gtkplaylist.h | 261 | ||||
-rw-r--r-- | plugins/gtkui/gtksession.c | 44 | ||||
-rw-r--r-- | plugins/gtkui/gtkui.c | 343 | ||||
-rw-r--r-- | plugins/gtkui/interface.c | 1737 | ||||
-rw-r--r-- | plugins/gtkui/interface.h | 12 |
13 files changed, 9634 insertions, 0 deletions
diff --git a/plugins/gtkui/Makefile.am b/plugins/gtkui/Makefile.am new file mode 100644 index 00000000..13ace983 --- /dev/null +++ b/plugins/gtkui/Makefile.am @@ -0,0 +1,15 @@ +#if HAVE_GTK +#gtkuidir = $(libdir)/$(PACKAGE) +#pkglib_LTLIBRARIES = gtkui.la +#gtkui_la_SOURCES = gtkui.c\ +# callbacks.c interface.c support.c callbacks.h interface.h support.h\ +# gtkplaylist.c gtkplaylist.h\ +# drawing.h gdkdrawing.c\ +# gtksession.c +# +# +#gtkui_la_LDFLAGS = -module +# +#gtkui_la_LIBADD = $(LDADD) $(GTKUI_DEPS_LIBS) +#AM_CFLAGS = -std=c99 $(GTKUI_DEPS_CFLAGS) +#endif diff --git a/plugins/gtkui/callbacks.c b/plugins/gtkui/callbacks.c new file mode 100644 index 00000000..8d6d9bbf --- /dev/null +++ b/plugins/gtkui/callbacks.c @@ -0,0 +1,1763 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtk/gtk.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <ctype.h> +#include <gdk/gdkkeysyms.h> + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#include "common.h" + +#include "playlist.h" +#include "gtkplaylist.h" +#include "messagepump.h" +#include "codec.h" +#include "playback.h" +#include "search.h" +#include "streamer.h" +#include "progress.h" +#include "volume.h" +#include "session.h" +#include "conf.h" + +#include "plugins.h" + +extern GtkWidget *mainwin; +extern gtkplaylist_t main_playlist; +extern gtkplaylist_t search_playlist; + +gboolean +playlist_tooltip_handler (GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, gpointer unused) +{ + playItem_t *item = gtkpl_get_for_idx (&main_playlist, main_playlist.scrollpos + y / rowheight); + if (item && item->fname) { + gtk_tooltip_set_text (tooltip, item->fname); + return TRUE; + } + return FALSE; +} + +void +main_playlist_init (GtkWidget *widget) { + // init playlist control structure, and put it into widget user-data + memset (&main_playlist, 0, sizeof (main_playlist)); + main_playlist.title = "playlist"; + main_playlist.playlist = widget; + main_playlist.header = lookup_widget (mainwin, "header"); + main_playlist.scrollbar = lookup_widget (mainwin, "playscroll"); + main_playlist.hscrollbar = lookup_widget (mainwin, "playhscroll"); + main_playlist.pcurr = &playlist_current_ptr; + main_playlist.pcount = &pl_count; + main_playlist.iterator = PL_MAIN; + main_playlist.multisel = 1; + main_playlist.scrollpos = 0; + main_playlist.hscrollpos = 0; + main_playlist.row = -1; + main_playlist.clicktime = -1; + main_playlist.nvisiblerows = 0; + +// FIXME: on 1st run, copy colwidths to new columns +// main_playlist.colwidths = session_get_main_colwidths_ptr (); + + DB_conf_item_t *col = conf_find ("playlist.column.", NULL); + if (!col) { + // create default set of columns + gtkpl_column_append (&main_playlist, gtkpl_column_alloc ("Playing", 50, DB_COLUMN_PLAYING, NULL, 0)); + gtkpl_column_append (&main_playlist, gtkpl_column_alloc ("Artist / Album", 150, DB_COLUMN_ARTIST_ALBUM, NULL, 0)); + gtkpl_column_append (&main_playlist, gtkpl_column_alloc ("Track №", 50, DB_COLUMN_TRACK, NULL, 1)); + gtkpl_column_append (&main_playlist, gtkpl_column_alloc ("Title / Track Artist", 150, DB_COLUMN_TITLE, NULL, 0)); + gtkpl_column_append (&main_playlist, gtkpl_column_alloc ("Duration", 50, DB_COLUMN_DURATION, NULL, 0)); + } + else { + while (col) { + gtkpl_append_column_from_textdef (&main_playlist, col->value); + col = conf_find ("playlist.column.", col); + } + } + + gtk_object_set_data (GTK_OBJECT (main_playlist.playlist), "ps", &main_playlist); + gtk_object_set_data (GTK_OBJECT (main_playlist.header), "ps", &main_playlist); + gtk_object_set_data (GTK_OBJECT (main_playlist.scrollbar), "ps", &main_playlist); + gtk_object_set_data (GTK_OBJECT (main_playlist.hscrollbar), "ps", &main_playlist); + + // FIXME: filepath should be in properties dialog, while tooltip should be + // used to show text that doesn't fit in column width + if (conf_get_int ("playlist.showpathtooltip", 0)) { + GValue value = {0, }; + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, TRUE); + g_object_set_property (G_OBJECT (widget), "has-tooltip", &value); + g_signal_connect (G_OBJECT (widget), "query-tooltip", G_CALLBACK (playlist_tooltip_handler), NULL); + } +} + +void +search_playlist_init (GtkWidget *widget) { + extern GtkWidget *searchwin; + // init playlist control structure, and put it into widget user-data + memset (&search_playlist, 0, sizeof (search_playlist)); + search_playlist.title = "search"; + search_playlist.playlist = widget; + search_playlist.header = lookup_widget (searchwin, "searchheader"); + search_playlist.scrollbar = lookup_widget (searchwin, "searchscroll"); + search_playlist.hscrollbar = lookup_widget (searchwin, "searchhscroll"); + assert (search_playlist.header); + assert (search_playlist.scrollbar); + // main_playlist.pcurr = &search_current; + search_playlist.pcount = &search_count; + search_playlist.multisel = 0; + search_playlist.iterator = PL_SEARCH; + search_playlist.scrollpos = 0; + search_playlist.hscrollpos = 0; + search_playlist.row = -1; + search_playlist.clicktime = -1; + search_playlist.nvisiblerows = 0; + +// FIXME: port to new columns +// search_playlist.colwidths = session_get_search_colwidths_ptr (); + // create default set of columns + DB_conf_item_t *col = conf_find ("search.column.", NULL); + if (!col) { + gtkpl_column_append (&search_playlist, gtkpl_column_alloc ("Artist / Album", 150, DB_COLUMN_ARTIST_ALBUM, NULL, 0)); + gtkpl_column_append (&search_playlist, gtkpl_column_alloc ("Track №", 50, DB_COLUMN_TRACK, NULL, 1)); + gtkpl_column_append (&search_playlist, gtkpl_column_alloc ("Title / Track Artist", 150, DB_COLUMN_TITLE, NULL, 0)); + gtkpl_column_append (&search_playlist, gtkpl_column_alloc ("Duration", 50, DB_COLUMN_DURATION, NULL, 0)); + } + else { + while (col) { + gtkpl_append_column_from_textdef (&search_playlist, col->value); + col = conf_find ("search.column.", col); + } + } + gtk_object_set_data (GTK_OBJECT (search_playlist.playlist), "ps", &search_playlist); + gtk_object_set_data (GTK_OBJECT (search_playlist.header), "ps", &search_playlist); + gtk_object_set_data (GTK_OBJECT (search_playlist.scrollbar), "ps", &search_playlist); + gtk_object_set_data (GTK_OBJECT (search_playlist.hscrollbar), "ps", &search_playlist); +} + +// redraw +gboolean +on_playlist_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + // draw visible area of playlist + gtkpl_expose (ps, event->area.x, event->area.y, event->area.width, event->area.height); + + return FALSE; +} + + +gboolean +on_playlist_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + if (event->button == 1) { + gtkpl_mouse1_pressed (ps, event->state, event->x, event->y, event->time); + } + return FALSE; +} + +gboolean +on_playlist_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + if (event->button == 1) { + gtkpl_mouse1_released (ps, event->state, event->x, event->y, event->time); + } + return FALSE; +} + +gboolean +on_playlist_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + gtkpl_mousemove (ps, event); + return FALSE; +} + + +void +on_playscroll_value_changed (GtkRange *widget, + gpointer user_data) +{ + GTKPL_PROLOGUE; + int newscroll = gtk_range_get_value (GTK_RANGE (widget)); + gtkpl_scroll (ps, newscroll); +} + +static gboolean +file_filter_func (const GtkFileFilterInfo *filter_info, gpointer data) { + // get ext + const char *p = filter_info->filename + strlen (filter_info->filename)-1; + while (p >= filter_info->filename) { + if (*p == '.') { + break; + } + p--; + } + if (*p != '.') { + return FALSE; + } + p++; + DB_decoder_t **codecs = plug_get_decoder_list (); + for (int i = 0; codecs[i]; i++) { + if (codecs[i]->exts && codecs[i]->insert) { + const char **exts = codecs[i]->exts; + if (exts) { + for (int e = 0; exts[e]; e++) { + if (!strcasecmp (exts[e], p)) { + return TRUE; + } + } + } + } + } + if (!strcasecmp (p, "pls")) { + return TRUE; + } + if (!strcasecmp (p, "m3u")) { + return TRUE; + } + return FALSE; +} + +static GtkFileFilter * +set_file_filter (GtkWidget *dlg, const char *name) { + if (!name) { + name = "Supported sound formats"; + } + + GtkFileFilter* flt; + flt = gtk_file_filter_new (); + gtk_file_filter_set_name (flt, name); + + gtk_file_filter_add_custom (flt, GTK_FILE_FILTER_FILENAME, file_filter_func, NULL, NULL); +#if 0 + DB_decoder_t **codecs = plug_get_decoder_list (); + for (int i = 0; codecs[i]; i++) { + if (codecs[i]->exts && codecs[i]->insert) { + const char **exts = codecs[i]->exts; + if (exts) { + for (int e = 0; exts[e]; e++) { + char filter[20]; + snprintf (filter, 20, "*.%s", exts[e]); + gtk_file_filter_add_pattern (flt, filter); + char *p; + for (p = filter; *p; p++) { + *p = toupper (*p); + } + gtk_file_filter_add_pattern (flt, filter); + } + } + } + } + gtk_file_filter_add_pattern (flt, "*.pls"); + gtk_file_filter_add_pattern (flt, "*.m3u"); +#endif + + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt); + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dlg), flt); + flt = gtk_file_filter_new (); + gtk_file_filter_set_name (flt, "Other files (*)"); + gtk_file_filter_add_pattern (flt, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt); +} + +void +on_open_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *dlg = gtk_file_chooser_dialog_new ("Open file(s)...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + + set_file_filter (dlg, NULL); + + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dlg), TRUE); + // restore folder + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dlg), conf_get_str ("filechooser.lastdir", "")); + int response = gtk_dialog_run (GTK_DIALOG (dlg)); + // store folder + gchar *folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dlg)); + if (folder) { + conf_set_str ("filechooser.lastdir", folder); + g_free (folder); + } + if (response == GTK_RESPONSE_OK) + { + pl_free (); + GSList *lst = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dlg)); + gtk_widget_destroy (dlg); + if (lst) { + messagepump_push (M_OPENFILES, (uintptr_t)lst, 0, 0); + } + } + else { + gtk_widget_destroy (dlg); + } +} + + +void +on_add_files_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *dlg = gtk_file_chooser_dialog_new ("Add file(s) to playlist...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + + set_file_filter (dlg, NULL); + + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dlg), TRUE); + + // restore folder + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dlg), conf_get_str ("filechooser.lastdir", "")); + int response = gtk_dialog_run (GTK_DIALOG (dlg)); + // store folder + gchar *folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dlg)); + if (folder) { + conf_set_str ("filechooser.lastdir", folder); + g_free (folder); + } + if (response == GTK_RESPONSE_OK) + { + GSList *lst = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dlg)); + gtk_widget_destroy (dlg); + if (lst) { + messagepump_push (M_ADDFILES, (uintptr_t)lst, 0, 0); + } + } + else { + gtk_widget_destroy (dlg); + } +} + +void +on_add_folders_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *dlg = gtk_file_chooser_dialog_new ("Add folder(s) to playlist...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + + set_file_filter (dlg, NULL); + + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dlg), TRUE); + // restore folder + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dlg), conf_get_str ("filechooser.lastdir", "")); + int response = gtk_dialog_run (GTK_DIALOG (dlg)); + // store folder + gchar *folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dlg)); + if (folder) { + conf_set_str ("filechooser.lastdir", folder); + g_free (folder); + } + if (response == GTK_RESPONSE_OK) + { + gchar *folder = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg)); + GSList *lst = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dlg)); + gtk_widget_destroy (dlg); + if (lst) { + messagepump_push (M_ADDDIRS, (uintptr_t)lst, 0, 0); + } + } + else { + gtk_widget_destroy (dlg); + } +} + + +void +on_preferences1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_quit_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + progress_abort (); + messagepump_push (M_TERMINATE, 0, 0, 0); +} + + +void +on_clear1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + pl_free (); + gtkplaylist_t *ps = &main_playlist; + GtkWidget *widget = ps->playlist; + gtkpl_setup_scrollbar (ps); + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + gtkpl_expose (ps, 0, 0, widget->allocation.width, widget->allocation.height); + search_refresh (); +} + + +void +on_select_all1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + pl_select_all (); + gtkplaylist_t *ps = &main_playlist; + GtkWidget *widget = ps->playlist; + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height); +} + + +void +on_remove1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + gtkplaylist_t *ps = &main_playlist; + GtkWidget *widget = ps->playlist; + ps->row = pl_delete_selected (); + if (ps->row != -1) { + playItem_t *it = pl_get_for_idx (ps->row); + if (it) { + it->selected = 1; + } + } + gtkpl_setup_scrollbar (ps); + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + gtkpl_expose (ps, 0, 0, widget->allocation.width, widget->allocation.height); + search_refresh (); +} + + +void +on_crop1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + gtkplaylist_t *ps = &main_playlist; + GtkWidget *widget = ps->playlist; + pl_crop_selected (); + gtkpl_setup_scrollbar (ps); + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + gtkpl_expose (ps, 0, 0, widget->allocation.width, widget->allocation.height); + search_refresh (); +} + + + +gboolean +on_playlist_scroll_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + GdkEventScroll *ev = (GdkEventScroll*)event; + gtkpl_handle_scroll_event (ps, ev->direction); + return FALSE; +} + + +void +on_stopbtn_clicked (GtkButton *button, + gpointer user_data) +{ + messagepump_push (M_STOPSONG, 0, 0, 0); +} + + +void +on_playbtn_clicked (GtkButton *button, + gpointer user_data) +{ + messagepump_push (M_PLAYSONG, 0, 0, 0); +} + + +void +on_pausebtn_clicked (GtkButton *button, + gpointer user_data) +{ + messagepump_push (M_PAUSESONG, 0, 0, 0); +} + + +void +on_prevbtn_clicked (GtkButton *button, + gpointer user_data) +{ + messagepump_push (M_PREVSONG, 0, 0, 0); +} + + +void +on_nextbtn_clicked (GtkButton *button, + gpointer user_data) +{ + messagepump_push (M_NEXTSONG, 0, 0, 0); +} + + +void +on_playrand_clicked (GtkButton *button, + gpointer user_data) +{ + messagepump_push (M_PLAYRANDOM, 0, 0, 0); +} + + +gboolean +on_mainwin_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + gtkpl_keypress (&main_playlist, event->keyval, event->state); + return FALSE; +} + + +void +on_playlist_drag_begin (GtkWidget *widget, + GdkDragContext *drag_context, + gpointer user_data) +{ +} + +gboolean +on_playlist_drag_motion (GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + guint time, + gpointer user_data) +{ + GTKPL_PROLOGUE; + gtkpl_track_dragdrop (ps, y); + return FALSE; +} + + +gboolean +on_playlist_drag_drop (GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + guint time, + gpointer user_data) +{ +#if 0 + if (drag_context->targets) { + GdkAtom target_type = GDK_POINTER_TO_ATOM (g_list_nth_data (drag_context->targets, TARGET_SAMEWIDGET)); + if (!target_type) { + return FALSE; + } + gtk_drag_get_data (widget, drag_context, target_type, time); + return TRUE; + } +#endif + return FALSE; +} + + +void +on_playlist_drag_data_get (GtkWidget *widget, + GdkDragContext *drag_context, + GtkSelectionData *selection_data, + guint target_type, + guint time, + gpointer user_data) +{ + switch (target_type) { + case TARGET_SAMEWIDGET: + { + // format as "STRING" consisting of array of pointers + int nsel = pl_getselcount (); + if (!nsel) { + break; // something wrong happened + } + uint32_t *ptr = malloc (nsel * sizeof (uint32_t)); + int idx = 0; + int i = 0; + for (playItem_t *it = playlist_head[PL_MAIN]; it; it = it->next[PL_MAIN], idx++) { + if (it->selected) { + ptr[i] = idx; + i++; + } + } + gtk_selection_data_set (selection_data, selection_data->target, sizeof (uint32_t) * 8, (gchar *)ptr, nsel * sizeof (uint32_t)); + free (ptr); + } + break; + default: + g_assert_not_reached (); + } +} + + +void +on_playlist_drag_data_received (GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *data, + guint target_type, + guint time, + gpointer user_data) +{ + GTKPL_PROLOGUE; + gchar *ptr=(char*)data->data; + if (target_type == 0) { // uris + fprintf (stderr, "calling gtkpl_handle_fm_drag_drop\n"); +// if (!strncmp(ptr,"file:///",8)) { + gtkpl_handle_fm_drag_drop (ps, y, ptr, data->length); +// } + } + else if (target_type == 1) { + uint32_t *d= (uint32_t *)ptr; + gtkpl_handle_drag_drop (ps, y, d, data->length/4); + } + gtk_drag_finish (drag_context, TRUE, FALSE, time); +} + + +void +on_playlist_drag_data_delete (GtkWidget *widget, + GdkDragContext *drag_context, + gpointer user_data) +{ +} + + +gboolean +on_playlist_drag_failed (GtkWidget *widget, + GdkDragContext *arg1, + GtkDragResult arg2, + gpointer user_data) +{ + return TRUE; +} + + +void +on_playlist_drag_leave (GtkWidget *widget, + GdkDragContext *drag_context, + guint time, + gpointer user_data) +{ + GTKPL_PROLOGUE; + gtkpl_track_dragdrop (ps, -1); +} + +void +on_voice1_clicked (GtkButton *button, + gpointer user_data) +{ + codec_lock (); + if (str_playing_song.decoder && str_playing_song.decoder->mutevoice) { + str_playing_song.decoder->mutevoice (0, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + } + codec_unlock (); +} + + +void +on_voice2_clicked (GtkButton *button, + gpointer user_data) +{ + codec_lock (); + if (str_playing_song.decoder && str_playing_song.decoder->mutevoice) { + str_playing_song.decoder->mutevoice (1, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + } + codec_unlock (); +} + + +void +on_voice3_clicked (GtkButton *button, + gpointer user_data) +{ + codec_lock (); + if (str_playing_song.decoder && str_playing_song.decoder->mutevoice) { + str_playing_song.decoder->mutevoice (2, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + } + codec_unlock (); +} + + +void +on_voice4_clicked (GtkButton *button, + gpointer user_data) +{ + codec_lock (); + if (str_playing_song.decoder && str_playing_song.decoder->mutevoice) { + str_playing_song.decoder->mutevoice (3, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + } + codec_unlock (); +} + + +void +on_voice5_clicked (GtkButton *button, + gpointer user_data) +{ + codec_lock (); + if (str_playing_song.decoder && str_playing_song.decoder->mutevoice) { + str_playing_song.decoder->mutevoice (4, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + } + codec_unlock (); +} + +void +on_order_linear_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + conf_set_int ("playback.order", 0); +} + + +void +on_order_shuffle_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + conf_set_int ("playback.order", 1); +} + + +void +on_order_random_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + conf_set_int ("playback.order", 2); +} + + +void +on_loop_all_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + conf_set_int ("playback.loop", 0); +} + + +void +on_loop_single_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + conf_set_int ("playback.loop", 2); +} + + +void +on_loop_disable_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + conf_set_int ("playback.loop", 1); +} + +void +on_playlist_realize (GtkWidget *widget, + gpointer user_data) +{ + GtkTargetEntry entry = { + .target = "STRING", + .flags = GTK_TARGET_SAME_WIDGET/* | GTK_TARGET_OTHER_APP*/, + TARGET_SAMEWIDGET + }; + // setup drag-drop source +// gtk_drag_source_set (widget, GDK_BUTTON1_MASK, &entry, 1, GDK_ACTION_MOVE); + // setup drag-drop target + gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, &entry, 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); + gtk_drag_dest_add_uri_targets (widget); +// gtk_drag_dest_set_track_motion (widget, TRUE); +} + +void +on_searchlist_realize (GtkWidget *widget, + gpointer user_data) +{ +} + + + + + +void +on_playlist_load_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *dlg = gtk_file_chooser_dialog_new ("Load Playlist", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + + GtkFileFilter* flt; + flt = gtk_file_filter_new (); + gtk_file_filter_set_name (flt, "DeaDBeeF playlist files (*.dbpl)"); + gtk_file_filter_add_pattern (flt, "*.dbpl"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt); + + if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_OK) + { + gchar *fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg)); + gtk_widget_destroy (dlg); + if (fname) { + int res = pl_load (fname); + printf ("load result: %d\n", res); + g_free (fname); + gtkplaylist_t *ps = &main_playlist; + gtkpl_setup_scrollbar (ps); + gtkpl_draw_playlist (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + gtkpl_expose (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + search_refresh (); + } + } + else { + gtk_widget_destroy (dlg); + } +} + +char last_playlist_save_name[1024] = ""; + +void +save_playlist_as (void) { + GtkWidget *dlg = gtk_file_chooser_dialog_new ("Save Playlist As", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); + + GtkFileFilter* flt; + flt = gtk_file_filter_new (); + gtk_file_filter_set_name (flt, "DeaDBeeF playlist files (*.dbpl)"); + gtk_file_filter_add_pattern (flt, "*.dbpl"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt); + + if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_OK) + { + gchar *fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg)); + gtk_widget_destroy (dlg); + + if (fname) { + int res = pl_save (fname); + printf ("save as res: %d\n", res); + if (res >= 0 && strlen (fname) < 1024) { + strcpy (last_playlist_save_name, fname); + } + g_free (fname); + } + } + else { + gtk_widget_destroy (dlg); + } +} + +void +on_playlist_save_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + if (!last_playlist_save_name[0]) { + save_playlist_as (); + } + else { + int res = pl_save (last_playlist_save_name); + printf ("save res: %d\n", res); + } +} + + +void +on_playlist_save_as_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + save_playlist_as (); +} + + +static GdkPixmap *seekbar_backbuf; + +enum +{ + CORNER_NONE = 0, + CORNER_TOPLEFT = 1, + CORNER_TOPRIGHT = 2, + CORNER_BOTTOMLEFT = 4, + CORNER_BOTTOMRIGHT = 8, + CORNER_ALL = 15 +}; + +static void +clearlooks_rounded_rectangle (cairo_t * cr, + double x, double y, double w, double h, + double radius, uint8_t corners) +{ + if (radius < 0.01 || (corners == CORNER_NONE)) { + cairo_rectangle (cr, x, y, w, h); + return; + } + + if (corners & CORNER_TOPLEFT) + cairo_move_to (cr, x + radius, y); + else + cairo_move_to (cr, x, y); + + if (corners & CORNER_TOPRIGHT) + cairo_arc (cr, x + w - radius, y + radius, radius, M_PI * 1.5, M_PI * 2); + else + cairo_line_to (cr, x + w, y); + + if (corners & CORNER_BOTTOMRIGHT) + cairo_arc (cr, x + w - radius, y + h - radius, radius, 0, M_PI * 0.5); + else + cairo_line_to (cr, x + w, y + h); + + if (corners & CORNER_BOTTOMLEFT) + cairo_arc (cr, x + radius, y + h - radius, radius, M_PI * 0.5, M_PI); + else + cairo_line_to (cr, x, y + h); + + if (corners & CORNER_TOPLEFT) + cairo_arc (cr, x + radius, y + radius, radius, M_PI, M_PI * 1.5); + else + cairo_line_to (cr, x, y); + +} + +int seekbar_moving = 0; +int seekbar_move_x = 0; + +void +seekbar_draw (GtkWidget *widget) { + if (!widget) { + return; + } + gdk_draw_rectangle (seekbar_backbuf, widget->style->bg_gc[0], TRUE, 0, 0, widget->allocation.width, widget->allocation.height); + cairo_t *cr; + cr = gdk_cairo_create (seekbar_backbuf); + if (!cr) { + return; + } + if (!str_playing_song.decoder || str_playing_song._duration < 0) { + clearlooks_rounded_rectangle (cr, 2, widget->allocation.height/2-4, widget->allocation.width-4, 8, 4, 0xff); + theme_set_cairo_source_rgb (cr, COLO_SEEKBAR_FRONT); + cairo_stroke (cr); + return; + } + float pos = 0; + if (seekbar_moving) { + int x = seekbar_move_x; + if (x < 0) { + x = 0; + } + if (x > widget->allocation.width-1) { + x = widget->allocation.width-1; + } + pos = x; + } + else { + if (str_playing_song.decoder && str_playing_song._duration > 0) { + pos = streamer_get_playpos () / str_playing_song._duration; + pos *= widget->allocation.width; + } + } + // left + if (pos > 0) { + theme_set_cairo_source_rgb (cr, COLO_SEEKBAR_FRONT); + cairo_rectangle (cr, 0, widget->allocation.height/2-4, pos, 8); + cairo_clip (cr); + clearlooks_rounded_rectangle (cr, 0, widget->allocation.height/2-4, widget->allocation.width, 8, 4, 0xff); + cairo_fill (cr); + cairo_reset_clip (cr); + } + + // right + theme_set_cairo_source_rgb (cr, COLO_SEEKBAR_BACK); + cairo_rectangle (cr, pos, widget->allocation.height/2-4, widget->allocation.width-pos, 8); + cairo_clip (cr); + clearlooks_rounded_rectangle (cr, 0, widget->allocation.height/2-4, widget->allocation.width, 8, 4, 0xff); + cairo_fill (cr); + cairo_reset_clip (cr); + + cairo_destroy (cr); +} + +void +seekbar_expose (GtkWidget *widget, int x, int y, int w, int h) { + gdk_draw_drawable (widget->window, widget->style->black_gc, seekbar_backbuf, x, y, x, y, w, h); +} + +gboolean +on_seekbar_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data) +{ + if (seekbar_backbuf) { + g_object_unref (seekbar_backbuf); + seekbar_backbuf = NULL; + } + seekbar_backbuf = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1); + seekbar_draw (widget); + return FALSE; +} + +gboolean +on_seekbar_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) +{ + seekbar_expose (widget, event->area.x, event->area.y, event->area.width, event->area.height); + return FALSE; +} + +gboolean +on_seekbar_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data) +{ + if (seekbar_moving) { + seekbar_move_x = event->x; + seekbar_draw (widget); + seekbar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height); + } + return FALSE; +} + +gboolean +on_seekbar_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + if (p_isstopped ()) { + return FALSE; + } + seekbar_moving = 1; + seekbar_move_x = event->x; + seekbar_draw (widget); + seekbar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height); + return FALSE; +} + + +gboolean +on_seekbar_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + seekbar_moving = 0; + seekbar_draw (widget); + seekbar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height); + float time = event->x * str_playing_song._duration / (widget->allocation.width); + if (time < 0) { + time = 0; + } + streamer_set_seek (time); +// messagepump_push (M_SONGSEEK, 0, time * 1000, 0); + return FALSE; +} + + + +static GdkPixmap *volumebar_backbuf; + +void +volumebar_draw (GtkWidget *widget) { + if (!widget) { + return; + } + gdk_draw_rectangle (volumebar_backbuf, widget->style->bg_gc[0], TRUE, 0, 0, widget->allocation.width, widget->allocation.height); + cairo_t *cr; + cr = gdk_cairo_create (volumebar_backbuf); + if (!cr) { + return; + } + float range = -volume_get_min_db (); + int n = widget->allocation.width / 4; + float vol = (range + volume_get_db ()) / range * n; + float h = 16; + for (int i = 0; i < n; i++) { + float iy = (float)i + 3; + if (i <= vol) { + theme_set_cairo_source_rgb (cr, COLO_VOLUMEBAR_FRONT); + } + else { + theme_set_cairo_source_rgb (cr, COLO_VOLUMEBAR_BACK); + } + cairo_rectangle (cr, i * 4, (widget->allocation.height/2-h/2) + h - 1 - (h* i / n), 3, h * iy / n); + cairo_fill (cr); + } + + cairo_destroy (cr); +} + +void +volumebar_expose (GtkWidget *widget, int x, int y, int w, int h) { + gdk_draw_drawable (widget->window, widget->style->black_gc, volumebar_backbuf, x, y, x, y, w, h); +} + +gboolean +on_volumebar_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data) +{ + if (volumebar_backbuf) { + g_object_unref (volumebar_backbuf); + volumebar_backbuf = NULL; + } + volumebar_backbuf = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1); + volumebar_draw (widget); + return FALSE; +} + +gboolean +on_volumebar_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) +{ + volumebar_expose (widget, event->area.x, event->area.y, event->area.width, event->area.height); + return FALSE; +} + + +gboolean +on_volumebar_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data) +{ + if (event->state & GDK_BUTTON1_MASK) { + float range = -volume_get_min_db (); + float volume = event->x / widget->allocation.width * range - range; + if (volume > 0) { + volume = 0; + } + if (volume < -range) { + volume = -range; + } + volume_set_db (volume); + volumebar_draw (widget); + volumebar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height); + } + return FALSE; +} + +gboolean +on_volumebar_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + float range = -volume_get_min_db (); + float volume = event->x / widget->allocation.width * range - range; + if (volume < -range) { + volume = -range; + } + if (volume > 0) { + volume = 0; + } + volume_set_db (volume); + volumebar_draw (widget); + volumebar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height); + return FALSE; +} + + +gboolean +on_volumebar_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + return FALSE; +} + +void +volumebar_notify_changed (void) { + GtkWidget *widget = lookup_widget (mainwin, "volumebar"); + volumebar_draw (widget); + volumebar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height); +} + +gboolean +on_mainwin_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + int conf_close_send_to_tray = conf_get_int ("close_send_to_tray", 0); + if (conf_close_send_to_tray) { + gtk_widget_hide (widget); + } + else { + messagepump_push (M_TERMINATE, 0, 0, 0); + } + return TRUE; +} + + + + +gboolean +on_volumebar_scroll_event (GtkWidget *widget, + GdkEventScroll *event, + gpointer user_data) +{ + float range = -volume_get_min_db (); + float vol = volume_get_db (); + if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT) { + vol += 1; + } + else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT) { + vol -= 1; + } + if (vol > 0) { + vol = 0; + } + else if (vol < -range) { + vol = -range; + } + volume_set_db (vol); + GtkWidget *volumebar = lookup_widget (mainwin, "volumebar"); + volumebar_draw (volumebar); + volumebar_expose (volumebar, 0, 0, volumebar->allocation.width, volumebar->allocation.height); + return FALSE; +} + + + +gboolean +on_mainwin_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data) +{ + session_capture_window_attrs ((uintptr_t)widget); + return FALSE; +} + + +void +on_scroll_follows_playback_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + conf_set_int ("playlist.scroll.followplayback", gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem))); +} + + +void +on_find_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + search_start (); +} + +void +show_info_window (const char *fname, const char *title) { + GtkWidget *widget = create_helpwindow (); + gtk_window_set_title (GTK_WINDOW (widget), title); + gtk_window_set_transient_for (GTK_WINDOW (widget), GTK_WINDOW (mainwin)); + GtkWidget *txt = lookup_widget (widget, "helptext"); + GtkTextBuffer *buffer = gtk_text_buffer_new (NULL); + + FILE *fp = fopen (fname, "rb"); + if (fp) { + fseek (fp, 0, SEEK_END); + size_t s = ftell (fp); + rewind (fp); + char buf[s+1]; + if (fread (buf, 1, s, fp) != s) { + fprintf (stderr, "error reading help file contents\n"); + const char *error = "Failed while reading help file"; + gtk_text_buffer_set_text (buffer, error, strlen (error)); + } + else { + buf[s] = 0; + gtk_text_buffer_set_text (buffer, buf, s); + } + fclose (fp); + } + else { + const char *error = "Failed to load help file"; + gtk_text_buffer_set_text (buffer, error, strlen (error)); + } + gtk_text_view_set_buffer (GTK_TEXT_VIEW (txt), buffer); + g_object_unref (buffer); + gtk_widget_show (widget); +} + +void +on_help1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + show_info_window (PREFIX "/share/doc/deadbeef/help.txt", "Help"); +} + +void +on_about1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + show_info_window (PREFIX "/share/doc/deadbeef/about.txt", "About DeaDBeeF " VERSION); +} + + +void +on_playhscroll_value_changed (GtkRange *widget, + gpointer user_data) +{ + GTKPL_PROLOGUE; + int newscroll = gtk_range_get_value (GTK_RANGE (widget)); + gtkpl_hscroll (ps, newscroll); +} + + +void +on_searchhscroll_value_changed (GtkRange *widget, + gpointer user_data) +{ + GTKPL_PROLOGUE; + int newscroll = gtk_range_get_value (GTK_RANGE (widget)); + gtkpl_hscroll (ps, newscroll); +} + + +gboolean +on_helpwindow_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + if (event->keyval == GDK_Escape) { + gtk_widget_hide (widget); + gtk_widget_destroy (widget); + } + return FALSE; +} + + +void +on_add_audio_cd_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + pl_add_file ("all.cda", NULL, NULL); + playlist_refresh (); +} + +static GtkWidget *prefwin; + +static char alsa_device_names[100][64]; +static int num_alsa_devices; + +static void +gtk_enum_sound_callback (const char *name, const char *desc, void *userdata) { + if (num_alsa_devices >= 100) { + fprintf (stderr, "wtf!! more than 100 alsa devices??\n"); + return; + } + GtkComboBox *combobox = GTK_COMBO_BOX (userdata); + gtk_combo_box_append_text (combobox, desc); + + if (!strcmp (conf_get_str ("alsa_soundcard", "default"), name)) { + gtk_combo_box_set_active (combobox, num_alsa_devices); + } + + strncpy (alsa_device_names[num_alsa_devices], name, 63); + alsa_device_names[num_alsa_devices][63] = 0; + num_alsa_devices++; +} + +void +on_preferences_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *w = prefwin = create_prefwin (); + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (mainwin)); + + // alsa_soundcard + + const char *s = conf_get_str ("alsa_soundcard", "default"); + GtkComboBox *combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_soundcard")); + gtk_combo_box_append_text (combobox, "Default Audio Device"); + if (!strcmp (s, "default")) { + gtk_combo_box_set_active (combobox, 0); + } + num_alsa_devices = 1; + strcpy (alsa_device_names[0], "default"); + palsa_enum_soundcards (gtk_enum_sound_callback, combobox); + + // alsa resampling + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_alsa_resampling")), conf_get_int ("alsa.resample", 0)); + + // alsa freeonstop + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_alsa_freewhenstopped")), conf_get_int ("alsa.freeonstop", 0)); + + // src_quality + combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_src_quality")); + gtk_combo_box_set_active (combobox, conf_get_int ("src_quality", 2)); + + // replaygain_mode + combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_replaygain_mode")); + gtk_combo_box_set_active (combobox, conf_get_int ("replaygain_mode", 0)); + + // replaygain_scale + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_replaygain_scale")), conf_get_int ("replaygain_scale", 1)); + + // close_send_to_tray + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_close_send_to_tray")), conf_get_int ("close_send_to_tray", 0)); + + // network + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_network_enableproxy")), conf_get_int ("network.proxy", 0)); + gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "pref_network_proxyaddress")), conf_get_str ("network.proxy.address", "")); + gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "pref_network_proxyport")), conf_get_str ("network.proxy.port", "8080")); + combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_network_proxytype")); + const char *type = conf_get_str ("network.proxy.type", "HTTP"); + if (!strcasecmp (type, "HTTP")) { + gtk_combo_box_set_active (combobox, 0); + } + else if (!strcasecmp (type, "HTTP_1_0")) { + gtk_combo_box_set_active (combobox, 1); + } + else if (!strcasecmp (type, "SOCKS4")) { + gtk_combo_box_set_active (combobox, 2); + } + else if (!strcasecmp (type, "SOCKS5")) { + gtk_combo_box_set_active (combobox, 3); + } + else if (!strcasecmp (type, "SOCKS4A")) { + gtk_combo_box_set_active (combobox, 4); + } + else if (!strcasecmp (type, "SOCKS5_HOSTNAME")) { + gtk_combo_box_set_active (combobox, 5); + } + + // list of plugins + GtkTreeView *tree = GTK_TREE_VIEW (lookup_widget (w, "pref_pluginlist")); + GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);//GTK_LIST_STORE (gtk_tree_view_get_model (tree)); + GtkCellRenderer *rend = gtk_cell_renderer_text_new (); + GtkTreeViewColumn *col = gtk_tree_view_column_new_with_attributes ("Title", rend, "text", 0, NULL); + gtk_tree_view_append_column (tree, col); + DB_plugin_t **plugins = plug_get_list (); + int i; + for (i = 0; plugins[i]; i++) { + GtkTreeIter it; + gtk_list_store_append (store, &it); + gtk_list_store_set (store, &it, 0, plugins[i]->name, -1); + } + gtk_tree_view_set_model (tree, GTK_TREE_MODEL (store)); + + gtk_widget_show (w); +} + + +void +on_pref_soundcard_changed (GtkComboBox *combobox, + gpointer user_data) +{ + int active = gtk_combo_box_get_active (combobox); + if (active >= 0 && active < num_alsa_devices) { + conf_set_str ("alsa_soundcard", alsa_device_names[active]); + messagepump_push (M_CONFIGCHANGED, 0, 0, 0); + } +} + +void +on_pref_alsa_resampling_clicked (GtkButton *button, + gpointer user_data) +{ + int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); + conf_set_int ("alsa.resample", active); + messagepump_push (M_CONFIGCHANGED, 0, 0, 0); +} + + +void +on_pref_src_quality_changed (GtkComboBox *combobox, + gpointer user_data) +{ + int active = gtk_combo_box_get_active (combobox); + conf_set_int ("src_quality", active == -1 ? 2 : active); + messagepump_push (M_CONFIGCHANGED, 0, 0, 0); +} + + +void +on_pref_replaygain_mode_changed (GtkComboBox *combobox, + gpointer user_data) +{ + int active = gtk_combo_box_get_active (combobox); + conf_set_int ("replaygain_mode", active == -1 ? 0 : active); + messagepump_push (M_CONFIGCHANGED, 0, 0, 0); +} + +void +on_pref_replaygain_scale_clicked (GtkButton *button, + gpointer user_data) +{ + int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); + conf_set_int ("replaygain_scale", active); + messagepump_push (M_CONFIGCHANGED, 0, 0, 0); +} + + +void +on_pref_close_send_to_tray_clicked (GtkButton *button, + gpointer user_data) +{ + int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); + conf_set_int ("close_send_to_tray", active); + messagepump_push (M_CONFIGCHANGED, 0, 0, 0); +} + + +void +on_pref_plugin_configure_activate (GtkButton *button, + gpointer user_data) +{ +} + +void +on_pref_pluginlist_cursor_changed (GtkTreeView *treeview, + gpointer user_data) +{ + GtkTreePath *path; + GtkTreeViewColumn *col; + gtk_tree_view_get_cursor (treeview, &path, &col); + if (!path || !col) { + // reset + return; + } + int *indices = gtk_tree_path_get_indices (path); + DB_plugin_t **plugins = plug_get_list (); + DB_plugin_t *p = plugins[*indices]; + assert (p); + GtkWidget *w = prefwin;//GTK_WIDGET (gtk_widget_get_parent_window (GTK_WIDGET (treeview))); + assert (w); + GtkEntry *e = GTK_ENTRY (lookup_widget (w, "pref_plugin_descr")); + gtk_entry_set_text (e, p->descr ? p->descr : ""); + e = GTK_ENTRY (lookup_widget (w, "pref_plugin_author")); + gtk_entry_set_text (e, p->author ? p->author : ""); + e = GTK_ENTRY (lookup_widget (w, "pref_plugin_email")); + gtk_entry_set_text (e, p->email ? p->email : ""); + e = GTK_ENTRY (lookup_widget (w, "pref_plugin_website")); + gtk_entry_set_text (e, p->website ? p->website : ""); +} + + + +void +on_artist_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_album_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_tracknum_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_duration_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_playing_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_title_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_custom_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_remove_column_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_pref_alsa_freewhenstopped_clicked (GtkButton *button, + gpointer user_data) +{ + int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)); + conf_set_int ("alsa.freeonstop", active); +} + +void +on_pref_network_proxyaddress_changed (GtkEditable *editable, + gpointer user_data) +{ + conf_set_str ("network.proxy.address", gtk_entry_get_text (GTK_ENTRY (editable))); +} + + +void +on_pref_network_enableproxy_clicked (GtkButton *button, + gpointer user_data) +{ + conf_set_int ("network.proxy", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))); +} + + +void +on_pref_network_proxyport_changed (GtkEditable *editable, + gpointer user_data) +{ + conf_set_int ("network.proxy.port", atoi (gtk_entry_get_text (GTK_ENTRY (editable)))); +} + + +void +on_pref_network_proxytype_changed (GtkComboBox *combobox, + gpointer user_data) +{ + + int active = gtk_combo_box_get_active (combobox); + switch (active) { + case 0: + conf_set_str ("network.proxy.type", "HTTP"); + break; + case 1: + conf_set_str ("network.proxy.type", "HTTP_1_0"); + break; + case 2: + conf_set_str ("network.proxy.type", "SOCKS4"); + break; + case 3: + conf_set_str ("network.proxy.type", "SOCKS5"); + break; + case 4: + conf_set_str ("network.proxy.type", "SOCKS4A"); + break; + case 5: + conf_set_str ("network.proxy.type", "SOCKS5_HOSTNAME"); + break; + default: + conf_set_str ("network.proxy.type", "HTTP"); + break; + } +} + + +gboolean +on_prefwin_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + if (event->keyval == GDK_Escape) { + gtk_widget_hide (widget); + gtk_widget_destroy (widget); + } + return FALSE; +} + + +static GtkWidget *addlocation_window; + +void +on_add_location_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *widget = addlocation_window = create_addlocation (); + gtk_window_set_transient_for (GTK_WINDOW (widget), GTK_WINDOW (mainwin)); + gtk_widget_show (widget); +} + +static void +add_location_destroy (void) { + if (addlocation_window) { + gtk_widget_hide (addlocation_window); + gtk_widget_destroy (addlocation_window); + addlocation_window = NULL; + } +} + +void +on_addlocation_entry_activate (GtkEntry *entry, + gpointer user_data) +{ + const char *text = gtk_entry_get_text (entry); + if (text) { + pl_add_file (text, NULL, NULL); + playlist_refresh (); + } + add_location_destroy (); +} + +void +on_addlocation_ok_clicked (GtkButton *button, + gpointer user_data) +{ + if (addlocation_window) { + GtkEntry *entry = GTK_ENTRY (lookup_widget (addlocation_window, "addlocation_entry")); + if (entry) { + const char *text = gtk_entry_get_text (entry); + if (text) { + pl_add_file (text, NULL, NULL); + playlist_refresh (); + } + } + } + add_location_destroy (); +} + +gboolean +on_addlocation_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + if (event->keyval == GDK_Escape) { + add_location_destroy (); + } + return FALSE; +} + + + + + + diff --git a/plugins/gtkui/callbacks.h b/plugins/gtkui/callbacks.h new file mode 100644 index 00000000..d2e3f61a --- /dev/null +++ b/plugins/gtkui/callbacks.h @@ -0,0 +1,694 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <gtk/gtk.h> + + +void +on_addbtn_clicked (GtkButton *button, + gpointer user_data); + +void +on_playbtn_clicked (GtkButton *button, + gpointer user_data); + +void +on_volume_value_changed (GtkRange *range, + gpointer user_data); + +void +on_playpos_value_changed (GtkRange *range, + gpointer user_data); + +gboolean +on_playlist_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +gboolean +on_playlist_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +void +on_playlist_realize (GtkWidget *widget, + gpointer user_data); + +gboolean +on_playlist_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +void +on_playscroll_value_changed (GtkRange *range, + gpointer user_data); + +void +on_open_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_add_files_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_add_folder1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_preferences1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_quit_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_clear1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_select_all1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_remove1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_crop1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_about1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +gboolean +on_playlist_scroll_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_stopbtn_clicked (GtkButton *button, + gpointer user_data); + +void +on_playbtn_clicked (GtkButton *button, + gpointer user_data); + +void +on_pausebtn_clicked (GtkButton *button, + gpointer user_data); + +void +on_prevbtn_clicked (GtkButton *button, + gpointer user_data); + +void +on_nextbtn_clicked (GtkButton *button, + gpointer user_data); + +void +on_playrand_clicked (GtkButton *button, + gpointer user_data); + +gboolean +on_mainwin_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_playlist_drag_begin (GtkWidget *widget, + GdkDragContext *drag_context, + gpointer user_data); + +gboolean +on_playlist_drag_motion (GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + guint time, + gpointer user_data); + +gboolean +on_playlist_drag_drop (GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + guint time, + gpointer user_data); + +void +on_playlist_drag_data_get (GtkWidget *widget, + GdkDragContext *drag_context, + GtkSelectionData *data, + guint info, + guint time, + gpointer user_data); + +void +on_playlist_drag_end (GtkWidget *widget, + GdkDragContext *drag_context, + gpointer user_data); + +gboolean +on_playlist_drag_failed (GtkWidget *widget, + GdkDragContext *arg1, + GtkDragResult arg2, + gpointer user_data); + +void +on_playlist_drag_leave (GtkWidget *widget, + GdkDragContext *drag_context, + guint time, + gpointer user_data); + +gboolean +on_playlist_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_playlist_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + +void +on_voice1_clicked (GtkButton *button, + gpointer user_data); + +void +on_voice2_clicked (GtkButton *button, + gpointer user_data); + +void +on_voice3_clicked (GtkButton *button, + gpointer user_data); + +void +on_voice4_clicked (GtkButton *button, + gpointer user_data); + +void +on_voice5_clicked (GtkButton *button, + gpointer user_data); + +void +on_playlist_drag_data_received (GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + gpointer user_data); + +void +on_playlist_drag_data_delete (GtkWidget *widget, + GdkDragContext *drag_context, + gpointer user_data); + +gboolean +on_header_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +gboolean +on_header_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +void +on_header_realize (GtkWidget *widget, + gpointer user_data); + +gboolean +on_header_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + +gboolean +on_header_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_header_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +void +on_order_linear_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_order_shuffle_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_order_random_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_loop_all_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_loop_single_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_loop_disable_activate (GtkMenuItem *menuitem, + gpointer user_data); + +gboolean +on_searchwin_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_searchentry_changed (GtkEditable *editable, + gpointer user_data); + +gboolean +on_searchheader_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_searchheader_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_searchheader_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +gboolean +on_searchheader_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +gboolean +on_searchheader_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + +gboolean +on_searchlist_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_searchlist_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +gboolean +on_searchlist_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +gboolean +on_searchlist_scroll_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_searchscroll_value_changed (GtkRange *range, + gpointer user_data); + +void +on_searchlist_realize (GtkWidget *widget, + gpointer user_data); + +gboolean +on_header_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_header_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_header_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +gboolean +on_header_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +gboolean +on_header_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + +gboolean +on_playlist_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_playlist_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +gboolean +on_playlist_scroll_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +gboolean +on_playlist_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_playlist_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + + +void +on_playscroll_value_changed (GtkRange *range, + gpointer user_data); + +void +on_playlist_load_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_playlist_save_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_playlist_save_as_activate (GtkMenuItem *menuitem, + gpointer user_data); + +gboolean +on_seekbar_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_seekbar_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_seekbar_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +gboolean +on_seekbar_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +gboolean +on_seekbar_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + +gboolean +on_volumebar_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_volumebar_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +gboolean +on_volumebar_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +gboolean +on_volumebar_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data); + +gboolean +on_volumebar_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data); + +void +on_main_quit (GtkObject *object, + gpointer user_data); + +gboolean +on_mainwin_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); +void +volumebar_draw (GtkWidget *widget); +void +volumebar_expose (GtkWidget *widget, int x, int y, int w, int h); + + + +void +on_progress_abort (GtkButton *button, + gpointer user_data); + +gboolean +on_addprogress_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +gboolean +on_volumebar_scroll_event (GtkWidget *widget, + GdkEventScroll *event, + gpointer user_data); + + +void +on_order_shuffle_activate (GtkMenuItem *menuitem, + gpointer user_data); + +gboolean +on_mainwin_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data); + +void +on_cursor_follows_playback_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_scroll_follows_playback_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_find_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_add_folders_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_clear1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_select_all1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_remove1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_find_activate (GtkMenuItem *menuitem, + gpointer user_data); + + +void +on_help1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_playhscroll_value_changed (GtkRange *range, + gpointer user_data); + +void +on_searchhscroll_value_changed (GtkRange *range, + gpointer user_data); + +gboolean +on_helpwindow_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_add_audio_cd_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_preferences_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_pref_soundcard_changed (GtkComboBox *combobox, + gpointer user_data); + +void +on_pref_samplerate_changed (GtkEditable *editable, + gpointer user_data); + +void +on_pref_src_quality_changed (GtkComboBox *combobox, + gpointer user_data); + +void +on_pref_replaygain_clicked (GtkButton *button, + gpointer user_data); + +void +on_pref_replaygain_scale_clicked (GtkButton *button, + gpointer user_data); + +void +on_pref_close_send_to_tray_clicked (GtkButton *button, + gpointer user_data); + +void +on_pref_plugin_configure_activate (GtkButton *button, + gpointer user_data); + +void +on_pref_src_quality_changed (GtkComboBox *combobox, + gpointer user_data); + +void +on_conf_replaygain_mode_changed (GtkComboBox *combobox, + gpointer user_data); + +void +on_pref_replaygain_mode_changed (GtkComboBox *combobox, + gpointer user_data); + +void +on_pref_pluginlist_cursor_changed (GtkTreeView *treeview, + gpointer user_data); + +gboolean +on_header_popup_menu (GtkWidget *widget, + gpointer user_data); + +void +on_artist_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_album_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_tracknum_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_duration_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_playing_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_title_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_custom_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_remove_column_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_pref_alsa_resampling_clicked (GtkButton *button, + gpointer user_data); + +void +on_pref_alsa_freewhenstopped_clicked (GtkButton *button, + gpointer user_data); + +void +on_pref_soundcard_editing_done (GtkCellEditable *celleditable, + gpointer user_data); + +void +on_pref_soundcard_changed (GtkComboBox *combobox, + gpointer user_data); + +void +on_pref_network_proxyaddress_changed (GtkEditable *editable, + gpointer user_data); + +void +on_pref_network_enableproxy_clicked (GtkButton *button, + gpointer user_data); + +void +on_pref_network_proxyport_changed (GtkEditable *editable, + gpointer user_data); + +void +on_pref_network_proxytype_changed (GtkComboBox *combobox, + gpointer user_data); + +gboolean +on_prefwin_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_addlocation_ok_activate (GtkButton *button, + gpointer user_data); + +gboolean +on_addlocation_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_add_location_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_location_activate (GtkEntry *entry, + gpointer user_data); + +void +on_addlocation_ok_clicked (GtkButton *button, + gpointer user_data); + +void +on_addlocation_entry_activate (GtkEntry *entry, + gpointer user_data); diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade new file mode 100644 index 00000000..c71e3a65 --- /dev/null +++ b/plugins/gtkui/deadbeef.glade @@ -0,0 +1,2493 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="mainwin"> + <property name="visible">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="title" translatable="yes">DeaDBeeF</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">500</property> + <property name="default_height">300</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="icon_name"></property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="key_press_event" handler="on_mainwin_key_press_event" last_modification_time="Thu, 30 Jul 2009 21:14:26 GMT"/> + <signal name="delete_event" handler="on_mainwin_delete_event" last_modification_time="Thu, 13 Aug 2009 20:35:55 GMT"/> + <signal name="configure_event" handler="on_mainwin_configure_event" last_modification_time="Sun, 23 Aug 2009 15:26:53 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkMenuBar" id="menubar1"> + <property name="visible">True</property> + <property name="pack_direction">GTK_PACK_DIRECTION_LTR</property> + <property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property> + + <child> + <widget class="GtkMenuItem" id="menuitem1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_File</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="menuitem1_menu"> + + <child> + <widget class="GtkImageMenuItem" id="open"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Open file(s)</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_open_activate" last_modification_time="Sat, 04 Jul 2009 12:57:58 GMT"/> + <accelerator key="O" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image120"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator2"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="add_files"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add file(s)</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_add_files_activate" last_modification_time="Sat, 04 Jul 2009 13:04:01 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image121"> + <property name="visible">True</property> + <property name="stock">gtk-add</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="add_folders"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add folder(s)</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_add_folders_activate" last_modification_time="Sun, 06 Sep 2009 17:51:40 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image122"> + <property name="visible">True</property> + <property name="stock">gtk-add</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="add_audio_cd"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add Audio CD</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_add_audio_cd_activate" last_modification_time="Sat, 10 Oct 2009 15:29:22 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image123"> + <property name="visible">True</property> + <property name="stock">gtk-add</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="add_location1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add location</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_add_location_activate" last_modification_time="Sat, 07 Nov 2009 18:03:26 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separatormenuitem1"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="quit"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Quit</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_quit_activate" last_modification_time="Sat, 04 Jul 2009 12:57:58 GMT"/> + <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image124"> + <property name="visible">True</property> + <property name="stock">gtk-quit</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="edit1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Edit</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="edit1_menu"> + + <child> + <widget class="GtkImageMenuItem" id="clear1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Clear</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_clear1_activate" last_modification_time="Sun, 06 Sep 2009 18:30:03 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image125"> + <property name="visible">True</property> + <property name="stock">gtk-clear</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="select_all1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Select all</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_select_all1_activate" last_modification_time="Sun, 06 Sep 2009 18:30:03 GMT"/> + <accelerator key="A" modifiers="GDK_CONTROL_MASK" signal="activate"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="selection1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Selection</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="selection1_menu"> + + <child> + <widget class="GtkImageMenuItem" id="remove1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Remove</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_remove1_activate" last_modification_time="Sun, 06 Sep 2009 18:30:03 GMT"/> + <accelerator key="Delete" modifiers="0" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image126"> + <property name="visible">True</property> + <property name="stock">gtk-remove</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="crop1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Crop</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_crop1_activate" last_modification_time="Sat, 04 Jul 2009 13:04:01 GMT"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="find1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Find</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_find_activate" last_modification_time="Sun, 06 Sep 2009 18:30:03 GMT"/> + <accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="activate"/> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator5"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="preferences"> + <property name="visible">True</property> + <property name="label" translatable="yes">Preferences</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_preferences_activate" last_modification_time="Sat, 10 Oct 2009 15:50:29 GMT"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="playlist1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Playlist</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="playlist1_menu"> + + <child> + <widget class="GtkMenuItem" id="playlist_load"> + <property name="visible">True</property> + <property name="label" translatable="yes">Load</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_playlist_load_activate" last_modification_time="Sun, 09 Aug 2009 19:04:52 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="playlist_save"> + <property name="visible">True</property> + <property name="label" translatable="yes">Save</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_playlist_save_activate" last_modification_time="Sun, 09 Aug 2009 19:04:52 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="playlist_save_as"> + <property name="visible">True</property> + <property name="label" translatable="yes">Save As</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_playlist_save_as_activate" last_modification_time="Sun, 09 Aug 2009 19:04:52 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="order1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Order</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="order1_menu"> + + <child> + <widget class="GtkRadioMenuItem" id="order_linear"> + <property name="visible">True</property> + <property name="label" translatable="yes">Linear</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <signal name="activate" handler="on_order_linear_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkRadioMenuItem" id="order_shuffle"> + <property name="visible">True</property> + <property name="label" translatable="yes">Shuffle</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="group">order_linear</property> + <signal name="activate" handler="on_order_shuffle_activate" last_modification_time="Fri, 21 Aug 2009 16:46:02 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkRadioMenuItem" id="order_random"> + <property name="visible">True</property> + <property name="label" translatable="yes">Random</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="group">order_linear</property> + <signal name="activate" handler="on_order_random_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="looping1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Looping</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="looping1_menu"> + + <child> + <widget class="GtkRadioMenuItem" id="loop_all"> + <property name="visible">True</property> + <property name="label" translatable="yes">Loop All</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <signal name="activate" handler="on_loop_all_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkRadioMenuItem" id="loop_single"> + <property name="visible">True</property> + <property name="label" translatable="yes">Loop Single Song</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="group">loop_all</property> + <signal name="activate" handler="on_loop_single_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkRadioMenuItem" id="loop_disable"> + <property name="visible">True</property> + <property name="label" translatable="yes">Don't Loop</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="group">loop_all</property> + <signal name="activate" handler="on_loop_disable_activate" last_modification_time="Sat, 08 Aug 2009 12:26:33 GMT"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="scroll_follows_playback"> + <property name="visible">True</property> + <property name="label" translatable="yes">Scroll follows playback</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <signal name="activate" handler="on_scroll_follows_playback_activate" last_modification_time="Wed, 02 Sep 2009 17:46:43 GMT"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="menuitem4"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Help</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="menuitem4_menu"> + + <child> + <widget class="GtkMenuItem" id="about1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_About</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_about1_activate" last_modification_time="Sat, 04 Jul 2009 12:57:58 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="help1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Help</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_help1_activate" last_modification_time="Tue, 08 Sep 2009 17:32:06 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image127"> + <property name="visible">True</property> + <property name="stock">gtk-help</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkButton" id="stopbtn"> + <property name="visible">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_stopbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:48:41 GMT"/> + <accelerator key="v" modifiers="0" signal="activate"/> + + <child> + <widget class="GtkImage" id="image7"> + <property name="visible">True</property> + <property name="pixbuf">stop_24.png</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="playbtn"> + <property name="visible">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_playbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:48:53 GMT"/> + <accelerator key="x" modifiers="0" signal="activate"/> + <accelerator key="Return" modifiers="0" signal="activate"/> + + <child> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="pixbuf">play_24.png</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="pausebtn"> + <property name="visible">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_pausebtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:49:01 GMT"/> + <accelerator key="c" modifiers="0" signal="activate"/> + <accelerator key="p" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child> + <widget class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="pixbuf">pause_24.png</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="prevbtn"> + <property name="visible">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_prevbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:49:08 GMT"/> + <accelerator key="z" modifiers="0" signal="activate"/> + + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="pixbuf">prev_24.png</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="nextbtn"> + <property name="visible">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_nextbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:49:12 GMT"/> + <accelerator key="b" modifiers="0" signal="activate"/> + + <child> + <widget class="GtkImage" id="image5"> + <property name="visible">True</property> + <property name="pixbuf">next_24.png</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="playrand"> + <property name="visible">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_playrand_clicked" last_modification_time="Sun, 05 Jul 2009 10:49:16 GMT"/> + <accelerator key="n" modifiers="0" signal="activate"/> + + <child> + <widget class="GtkImage" id="image6"> + <property name="visible">True</property> + <property name="pixbuf">random_24.png</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkDrawingArea" id="volumebar"> + <property name="width_request">70</property> + <property name="visible">True</property> + <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="button_press_event" handler="on_volumebar_button_press_event" last_modification_time="Tue, 11 Aug 2009 18:57:49 GMT"/> + <signal name="button_release_event" handler="on_volumebar_button_release_event" last_modification_time="Tue, 11 Aug 2009 18:57:51 GMT"/> + <signal name="configure_event" handler="on_volumebar_configure_event" last_modification_time="Tue, 11 Aug 2009 18:57:55 GMT"/> + <signal name="expose_event" handler="on_volumebar_expose_event" last_modification_time="Tue, 11 Aug 2009 18:58:00 GMT"/> + <signal name="motion_notify_event" handler="on_volumebar_motion_notify_event" last_modification_time="Tue, 11 Aug 2009 18:58:05 GMT"/> + <signal name="scroll_event" handler="on_volumebar_scroll_event" last_modification_time="Tue, 18 Aug 2009 18:44:31 GMT"/> + </widget> + <packing> + <property name="padding">2</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkDrawingArea" id="seekbar"> + <property name="width_request">200</property> + <property name="visible">True</property> + <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="button_press_event" handler="on_seekbar_button_press_event" last_modification_time="Tue, 11 Aug 2009 17:47:59 GMT"/> + <signal name="button_release_event" handler="on_seekbar_button_release_event" last_modification_time="Tue, 11 Aug 2009 17:48:02 GMT"/> + <signal name="configure_event" handler="on_seekbar_configure_event" last_modification_time="Tue, 11 Aug 2009 17:48:06 GMT"/> + <signal name="expose_event" handler="on_seekbar_expose_event" last_modification_time="Tue, 11 Aug 2009 17:48:11 GMT"/> + <signal name="motion_notify_event" handler="on_seekbar_motion_notify_event" last_modification_time="Tue, 11 Aug 2009 17:48:18 GMT"/> + </widget> + <packing> + <property name="padding">2</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkHBox" id=" "> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkDrawingArea" id="header"> + <property name="height_request">24</property> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="expose_event" handler="on_header_expose_event" last_modification_time="Thu, 06 Aug 2009 14:54:29 GMT"/> + <signal name="configure_event" handler="on_header_configure_event" last_modification_time="Thu, 06 Aug 2009 14:54:33 GMT"/> + <signal name="realize" handler="on_header_realize" last_modification_time="Thu, 06 Aug 2009 14:54:41 GMT"/> + <signal name="motion_notify_event" handler="on_header_motion_notify_event" last_modification_time="Thu, 06 Aug 2009 16:33:54 GMT"/> + <signal name="button_press_event" handler="on_header_button_press_event" last_modification_time="Thu, 06 Aug 2009 16:42:32 GMT"/> + <signal name="button_release_event" handler="on_header_button_release_event" last_modification_time="Thu, 06 Aug 2009 16:47:31 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkDrawingArea" id="playlist"> + <property name="visible">True</property> + <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK</property> + <signal name="configure_event" handler="on_playlist_configure_event" last_modification_time="Sat, 04 Jul 2009 00:03:23 GMT"/> + <signal name="expose_event" handler="on_playlist_expose_event" last_modification_time="Sat, 04 Jul 2009 00:03:29 GMT"/> + <signal name="realize" handler="on_playlist_realize" last_modification_time="Sat, 04 Jul 2009 00:03:36 GMT"/> + <signal name="button_press_event" handler="on_playlist_button_press_event" last_modification_time="Sat, 04 Jul 2009 00:41:38 GMT"/> + <signal name="scroll_event" handler="on_playlist_scroll_event" last_modification_time="Sat, 04 Jul 2009 17:16:21 GMT"/> + <signal name="drag_begin" handler="on_playlist_drag_begin" last_modification_time="Fri, 31 Jul 2009 10:36:23 GMT"/> + <signal name="drag_motion" handler="on_playlist_drag_motion" last_modification_time="Fri, 31 Jul 2009 10:36:30 GMT"/> + <signal name="drag_drop" handler="on_playlist_drag_drop" last_modification_time="Fri, 31 Jul 2009 10:36:39 GMT"/> + <signal name="drag_data_get" handler="on_playlist_drag_data_get" last_modification_time="Fri, 31 Jul 2009 10:36:43 GMT"/> + <signal name="drag_end" handler="on_playlist_drag_end" last_modification_time="Fri, 31 Jul 2009 11:41:00 GMT"/> + <signal name="drag_failed" handler="on_playlist_drag_failed" last_modification_time="Fri, 31 Jul 2009 11:41:05 GMT"/> + <signal name="drag_leave" handler="on_playlist_drag_leave" last_modification_time="Fri, 31 Jul 2009 11:41:11 GMT"/> + <signal name="button_release_event" handler="on_playlist_button_release_event" last_modification_time="Fri, 31 Jul 2009 12:20:56 GMT"/> + <signal name="motion_notify_event" handler="on_playlist_motion_notify_event" last_modification_time="Fri, 31 Jul 2009 12:23:49 GMT"/> + <signal name="drag_data_received" handler="on_playlist_drag_data_received" last_modification_time="Mon, 03 Aug 2009 12:07:39 GMT"/> + <signal name="drag_data_delete" handler="on_playlist_drag_data_delete" last_modification_time="Mon, 03 Aug 2009 12:35:47 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkVScrollbar" id="playscroll"> + <property name="visible">True</property> + <property name="update_policy">GTK_UPDATE_CONTINUOUS</property> + <property name="inverted">False</property> + <property name="adjustment">0 0 1 1 0 0</property> + <signal name="value_changed" handler="on_playscroll_value_changed" last_modification_time="Sat, 04 Jul 2009 01:42:24 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkHScrollbar" id="playhscroll"> + <property name="visible">True</property> + <property name="update_policy">GTK_UPDATE_CONTINUOUS</property> + <property name="inverted">False</property> + <property name="adjustment">0 0 0 0 0 0</property> + <signal name="value_changed" handler="on_playhscroll_value_changed" last_modification_time="Sun, 13 Sep 2009 09:53:45 GMT"/> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkStatusbar" id="statusbar"> + <property name="visible">True</property> + <property name="has_resize_grip">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="searchwin"> + <property name="width_request">600</property> + <property name="height_request">150</property> + <property name="visible">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="title" translatable="yes">Search</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">True</property> + <property name="skip_pager_hint">True</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="key_press_event" handler="on_searchwin_key_press_event" last_modification_time="Sat, 08 Aug 2009 18:19:17 GMT"/> + <signal name="delete_event" handler="gtk_widget_hide_on_delete" last_modification_time="Sat, 08 Aug 2009 23:03:33 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="border_width">4</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkEntry" id="searchentry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">True</property> + <signal name="changed" handler="on_searchentry_changed" last_modification_time="Sat, 08 Aug 2009 18:18:17 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table2"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkVScrollbar" id="searchscroll"> + <property name="visible">True</property> + <property name="update_policy">GTK_UPDATE_CONTINUOUS</property> + <property name="inverted">False</property> + <property name="adjustment">0 0 1 1 0 0</property> + <signal name="value_changed" handler="on_playscroll_value_changed" last_modification_time="Sat, 08 Aug 2009 23:47:34 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkDrawingArea" id="searchheader"> + <property name="height_request">24</property> + <property name="visible">True</property> + <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="button_press_event" handler="on_header_button_press_event" last_modification_time="Sat, 08 Aug 2009 22:38:34 GMT"/> + <signal name="button_release_event" handler="on_header_button_release_event" last_modification_time="Sat, 08 Aug 2009 22:38:38 GMT"/> + <signal name="configure_event" handler="on_header_configure_event" last_modification_time="Sat, 08 Aug 2009 22:38:42 GMT"/> + <signal name="expose_event" handler="on_header_expose_event" last_modification_time="Sat, 08 Aug 2009 22:38:46 GMT"/> + <signal name="motion_notify_event" handler="on_header_motion_notify_event" last_modification_time="Sat, 08 Aug 2009 22:38:49 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkDrawingArea" id="searchlist"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK</property> + <signal name="button_press_event" handler="on_playlist_button_press_event" last_modification_time="Sat, 08 Aug 2009 22:37:04 GMT"/> + <signal name="configure_event" handler="on_searchlist_configure_event" last_modification_time="Sat, 08 Aug 2009 18:51:52 GMT"/> + <signal name="expose_event" handler="on_playlist_expose_event" last_modification_time="Sat, 08 Aug 2009 22:36:26 GMT"/> + <signal name="scroll_event" handler="on_playlist_scroll_event" last_modification_time="Sat, 08 Aug 2009 22:36:45 GMT"/> + <signal name="realize" handler="on_searchlist_realize" last_modification_time="Sat, 08 Aug 2009 19:12:45 GMT"/> + <signal name="button_release_event" handler="on_playlist_button_release_event" last_modification_time="Sat, 08 Aug 2009 22:37:24 GMT"/> + <signal name="motion_notify_event" handler="on_playlist_motion_notify_event" last_modification_time="Sat, 08 Aug 2009 22:38:04 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkHScrollbar" id="searchhscroll"> + <property name="visible">True</property> + <property name="update_policy">GTK_UPDATE_CONTINUOUS</property> + <property name="inverted">False</property> + <property name="adjustment">0 0 0 0 0 0</property> + <signal name="value_changed" handler="on_searchhscroll_value_changed" last_modification_time="Sun, 13 Sep 2009 10:07:12 GMT"/> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkMenu" id="traymenu"> + + <child> + <widget class="GtkImageMenuItem" id="stop2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Stop</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_stopbtn_clicked" last_modification_time="Sun, 06 Sep 2009 18:34:01 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image59"> + <property name="visible">True</property> + <property name="stock">gtk-media-stop</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="play2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Play</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_playbtn_clicked" last_modification_time="Sun, 06 Sep 2009 18:34:01 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image60"> + <property name="visible">True</property> + <property name="stock">gtk-media-play</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="pause2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Pause</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_pausebtn_clicked" last_modification_time="Sun, 06 Sep 2009 18:34:01 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image61"> + <property name="visible">True</property> + <property name="stock">gtk-media-pause</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="previous2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Previous</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_prevbtn_clicked" last_modification_time="Sun, 06 Sep 2009 18:34:01 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image62"> + <property name="visible">True</property> + <property name="stock">gtk-media-previous</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="next2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Next</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_nextbtn_clicked" last_modification_time="Sun, 06 Sep 2009 18:34:01 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image63"> + <property name="visible">True</property> + <property name="stock">gtk-media-next</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="play_random1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Play Random</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_playrand_clicked" last_modification_time="Sun, 16 Aug 2009 14:48:58 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator4"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="about3"> + <property name="visible">True</property> + <property name="label" translatable="yes">About</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_about1_activate" last_modification_time="Sun, 06 Sep 2009 18:34:01 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image64"> + <property name="visible">True</property> + <property name="stock">gtk-about</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator3"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="quit"> + <property name="visible">True</property> + <property name="label" translatable="yes">Quit</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_quit_activate" last_modification_time="Sun, 16 Aug 2009 14:45:24 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image65"> + <property name="visible">True</property> + <property name="stock">gtk-quit</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="addprogress"> + <property name="visible">True</property> + <property name="title" translatable="yes">Adding files...</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">True</property> + <property name="skip_pager_hint">True</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="delete_event" handler="on_addprogress_delete_event" last_modification_time="Sun, 16 Aug 2009 17:20:03 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="border_width">4</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkEntry" id="progresstitle"> + <property name="width_request">500</property> + <property name="visible">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label22"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button1"> + <property name="width_request">83</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Abort</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_progress_abort" last_modification_time="Sun, 16 Aug 2009 17:17:12 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">2</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="helpwindow"> + <property name="width_request">600</property> + <property name="height_request">400</property> + <property name="visible">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="title" translatable="yes">Help</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">True</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="key_press_event" handler="on_helpwindow_key_press_event" last_modification_time="Sun, 04 Oct 2009 19:06:07 GMT"/> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTextView" id="helptext"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_WORD</property> + <property name="cursor_visible">True</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">10</property> + <property name="right_margin">10</property> + <property name="indent">0</property> + <property name="text" translatable="yes"></property> + </widget> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="prefwin"> + <property name="width_request">642</property> + <property name="height_request">372</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Preferences</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="key_press_event" handler="on_prefwin_key_press_event" last_modification_time="Sat, 07 Nov 2009 15:47:40 GMT"/> + + <child> + <widget class="GtkNotebook" id="notebook2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">True</property> + <property name="show_border">True</property> + <property name="tab_pos">GTK_POS_TOP</property> + <property name="scrollable">False</property> + <property name="enable_popup">False</property> + + <child> + <widget class="GtkTable" id="table3"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="n_rows">6</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">3</property> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Output device</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">Software ALSA resampling</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">SRC quality (libsamplerate)</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">Replaygain mode</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">Replaygain peak scale</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label15"> + <property name="visible">True</property> + <property name="label" translatable="yes">Release ALSA while stopped</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="pref_alsa_resampling"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="clicked" handler="on_pref_alsa_resampling_clicked" last_modification_time="Sat, 24 Oct 2009 16:50:34 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="pref_replaygain_scale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="clicked" handler="on_pref_replaygain_scale_clicked" last_modification_time="Sat, 10 Oct 2009 18:52:10 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="pref_alsa_freewhenstopped"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="clicked" handler="on_pref_alsa_freewhenstopped_clicked" last_modification_time="Sat, 07 Nov 2009 11:37:02 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="pref_soundcard"> + <property name="visible">True</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + <signal name="changed" handler="on_pref_soundcard_changed" last_modification_time="Sat, 07 Nov 2009 14:12:28 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="pref_src_quality"> + <property name="visible">True</property> + <property name="items" translatable="yes">sinc_best_quality +sinc_medium_quality +sinc_fastest +sinc_zero_order_hold +linear</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + <signal name="changed" handler="on_pref_src_quality_changed" last_modification_time="Sat, 10 Oct 2009 19:02:36 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="pref_replaygain_mode"> + <property name="visible">True</property> + <property name="items" translatable="yes">Disable +Track +Album</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + <signal name="changed" handler="on_pref_replaygain_mode_changed" last_modification_time="Sat, 10 Oct 2009 19:22:23 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="Sound"> + <property name="visible">True</property> + <property name="label" translatable="yes">Sound</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table4"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="n_rows">1</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">3</property> + + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Close minimizes to tray</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="pref_close_send_to_tray"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="clicked" handler="on_pref_close_send_to_tray_clicked" last_modification_time="Sat, 10 Oct 2009 18:52:15 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">GUI</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table6"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">3</property> + + <child> + <widget class="GtkLabel" id="label17"> + <property name="visible">True</property> + <property name="label" translatable="yes">Enable proxy server</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label18"> + <property name="visible">True</property> + <property name="label" translatable="yes">Proxy server address</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="pref_network_proxyaddress"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + <signal name="changed" handler="on_pref_network_proxyaddress_changed" last_modification_time="Sat, 07 Nov 2009 15:13:12 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="pref_network_enableproxy"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="clicked" handler="on_pref_network_enableproxy_clicked" last_modification_time="Sat, 07 Nov 2009 15:12:34 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label19"> + <property name="visible">True</property> + <property name="label" translatable="yes">Proxy server port</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="pref_network_proxyport"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + <signal name="changed" handler="on_pref_network_proxyport_changed" last_modification_time="Sat, 07 Nov 2009 15:13:18 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label20"> + <property name="visible">True</property> + <property name="label" translatable="yes">Proxy type</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="pref_network_proxytype"> + <property name="visible">True</property> + <property name="items" translatable="yes">HTTP +HTTP_1_0 +SOCKS4 +SOCKS5 +SOCKS4A +SOCKS5_HOSTNAME</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + <signal name="changed" handler="on_pref_network_proxytype_changed" last_modification_time="Sat, 07 Nov 2009 15:36:03 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label16"> + <property name="visible">True</property> + <property name="label" translatable="yes">Network</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkHPaned" id="hpaned1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <property name="width_request">280</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="pref_pluginlist"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + <signal name="cursor_changed" handler="on_pref_pluginlist_cursor_changed" last_modification_time="Sat, 10 Oct 2009 19:54:17 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table5"> + <property name="width_request">400</property> + <property name="visible">True</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes">Description</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="label" translatable="yes">Author(s)</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="label" translatable="yes">Email</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label14"> + <property name="visible">True</property> + <property name="label" translatable="yes">Website</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="pref_plugin_descr"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">●</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="pref_plugin_author"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">●</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="pref_plugin_email"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">●</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="pref_plugin_website"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">●</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Plugins</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkMenu" id="headermenu"> + + <child> + <widget class="GtkMenuItem" id="add_column"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add column</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="add_column_menu"> + + <child> + <widget class="GtkMenuItem" id="artist"> + <property name="visible">True</property> + <property name="label" translatable="yes">Artist</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_artist_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="album"> + <property name="visible">True</property> + <property name="label" translatable="yes">Album</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_album_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="tracknum"> + <property name="visible">True</property> + <property name="label" translatable="yes">Track number</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_tracknum_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="duration"> + <property name="visible">True</property> + <property name="label" translatable="yes">Duration</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_duration_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="playing"> + <property name="visible">True</property> + <property name="label" translatable="yes">Playing status</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_playing_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="title"> + <property name="visible">True</property> + <property name="label" translatable="yes">Title</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_title_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator7"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="custom"> + <property name="visible">True</property> + <property name="label" translatable="yes">Custom</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_custom_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="remove_column"> + <property name="visible">True</property> + <property name="label" translatable="yes">Remove this column</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_remove_column_activate" last_modification_time="Mon, 19 Oct 2009 19:30:04 GMT"/> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="addlocation"> + <property name="visible">True</property> + <property name="title" translatable="yes">Add Location</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">True</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="key_press_event" handler="on_addlocation_key_press_event" last_modification_time="Sat, 07 Nov 2009 17:25:40 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="border_width">4</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkEntry" id="addlocation_entry"> + <property name="width_request">346</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + <signal name="activate" handler="on_addlocation_entry_activate" last_modification_time="Sat, 07 Nov 2009 18:13:04 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox8"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label21"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="addlocation_ok"> + <property name="width_request">83</property> + <property name="visible">True</property> + <property name="label" translatable="yes">OK</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_addlocation_ok_clicked" last_modification_time="Sat, 07 Nov 2009 18:12:00 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">2</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/plugins/gtkui/deadbeef.gladep b/plugins/gtkui/deadbeef.gladep new file mode 100644 index 00000000..22ea860c --- /dev/null +++ b/plugins/gtkui/deadbeef.gladep @@ -0,0 +1,10 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd"> + +<glade-project> + <name>Deadbeef</name> + <program_name>deadbeef</program_name> + <source_directory></source_directory> + <gnome_support>FALSE</gnome_support> + <gettext_support>FALSE</gettext_support> +</glade-project> diff --git a/plugins/gtkui/drawing.h b/plugins/gtkui/drawing.h new file mode 100644 index 00000000..23c350b6 --- /dev/null +++ b/plugins/gtkui/drawing.h @@ -0,0 +1,74 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef __DRAWING_H +#define __DRAWING_H + +#include <stdint.h> + +// abstract api for drawing primitives + +void +draw_init (void); + +void +draw_free (void); + +void +draw_begin (uintptr_t canvas); + +void +draw_end (void); + +uintptr_t +draw_load_pixbuf (const char *fname); + +void +draw_get_canvas_size (uintptr_t canvas, int *w, int *h); + +void +draw_copy (uintptr_t dest_canvas, uintptr_t src_canvas, int dx, int dy, int sx, int sy, int w, int h); + +void +draw_pixbuf (uintptr_t dest_canvas, uintptr_t pixbuf, int dx, int dy, int sx, int sy, int w, int h); + +void +draw_set_fg_color (float *rgb); + +void +draw_set_bg_color (float *rgb); + +void +draw_line (float x1, float y1, float x2, float y2); + +void +draw_rect (float x, float y, float w, float h, int fill); + +float +draw_get_font_size (void); + +void +draw_text (float x, float y, int width, int align, const char *text); + +void +draw_text_with_colors (float x, float y, int width, int align, const char *text); + +void +draw_get_text_extents (const char *text, int len, int *w, int *h); + +#endif // __DRAWING_H diff --git a/plugins/gtkui/gdkdrawing.c b/plugins/gtkui/gdkdrawing.c new file mode 100644 index 00000000..621ee92e --- /dev/null +++ b/plugins/gtkui/gdkdrawing.c @@ -0,0 +1,150 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> +#include "drawing.h" +#include "support.h" + +static GdkDrawable *drawable; +static GdkGC *gc; +static GdkColor clrfg; +static GdkColor clrbg; +static int pango_ready; +static PangoContext *pangoctx; +static PangoLayout *pangolayout; + +void +draw_begin (uintptr_t canvas) { + drawable = GDK_DRAWABLE (canvas); + gc = gdk_gc_new (drawable); +} + +void +draw_end (void) { +// if (pango_ready) { +// g_object_unref (pangolayout); +// g_object_unref (pangoctx); +// pango_ready = 0; +// } + drawable = NULL; + if (gc) { + g_object_unref (gc); + gc = NULL; + } +} + +void +draw_copy (uintptr_t dest_canvas, uintptr_t src_canvas, int dx, int dy, int sx, int sy, int w, int h) { + gdk_draw_drawable (GDK_DRAWABLE (dest_canvas), gc, GDK_DRAWABLE (src_canvas), dx, dy, sx, sy, w, h); +} + +uintptr_t +draw_load_pixbuf (const char *fname) { + return (uintptr_t)create_pixbuf (fname); +} + +void +draw_pixbuf (uintptr_t dest_canvas, uintptr_t pixbuf, int dx, int dy, int sx, int sy, int w, int h) { + gdk_pixbuf_render_to_drawable (GDK_PIXBUF (pixbuf), GDK_DRAWABLE (dest_canvas), gc, sx, sy, dx, dy, w, h, GDK_RGB_DITHER_NONE, 0, 0); +} + +void +draw_get_canvas_size (uintptr_t canvas, int *w, int *h) { + gdk_drawable_get_size (GDK_DRAWABLE (canvas), w, h); +} + +void +draw_set_fg_color (float *rgb) { + clrfg.red = rgb[0] * 0xffff; + clrfg.green = rgb[1] * 0xffff; + clrfg.blue = rgb[2] * 0xffff; + gdk_gc_set_rgb_fg_color (gc, &clrfg); +} + +void +draw_set_bg_color (float *rgb) { + clrbg.red = rgb[0] * 0xffff; + clrbg.green = rgb[1] * 0xffff; + clrbg.blue = rgb[2] * 0xffff; + gdk_gc_set_rgb_bg_color (gc, &clrbg); +} + +void +draw_line (float x1, float y1, float x2, float y2) { + gdk_draw_line (drawable, gc, x1, y1, x2, y2); +} + +void +draw_rect (float x, float y, float w, float h, int fill) { + gdk_draw_rectangle (drawable, gc, fill, x, y, w, h); +} + +static inline void +draw_init_font (void) { + if (!pango_ready) { + pangoctx = gdk_pango_context_get (); + pangolayout = pango_layout_new (pangoctx); + pango_layout_set_ellipsize (pangolayout, PANGO_ELLIPSIZE_END); + GtkStyle *style = gtk_widget_get_default_style (); + PangoFontDescription *desc = style->font_desc; + pango_layout_set_font_description (pangolayout, desc); + pango_ready = 1; + } +} + +float +draw_get_font_size (void) { + GdkScreen *screen = gdk_screen_get_default (); + float dpi = gdk_screen_get_resolution (screen); + GtkStyle *style = gtk_widget_get_default_style (); + PangoFontDescription *desc = style->font_desc; + return (float)pango_font_description_get_size (desc) / PANGO_SCALE * dpi / 72; +} + +void +draw_text (float x, float y, int width, int align, const char *text) { + draw_init_font (); + pango_layout_set_width (pangolayout, width*PANGO_SCALE); + pango_layout_set_alignment (pangolayout, align ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT); + pango_layout_set_text (pangolayout, text, -1); + gdk_draw_layout (drawable, gc, x, y, pangolayout); +} + +void +draw_text_with_colors (float x, float y, int width, int align, const char *text) { + draw_init_font (); + pango_layout_set_width (pangolayout, width*PANGO_SCALE); + pango_layout_set_alignment (pangolayout, align ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT); + pango_layout_set_text (pangolayout, text, -1); + gdk_draw_layout_with_colors (drawable, gc, x, y, pangolayout, &clrfg, &clrbg); +} + +void +draw_get_text_extents (const char *text, int len, int *w, int *h) { + draw_init_font (); + pango_layout_set_text (pangolayout, text, len); + PangoRectangle ext; + pango_layout_get_pixel_extents (pangolayout, &ext, NULL); + *w = ext.width; + *h = ext.height; +} diff --git a/plugins/gtkui/gtkplaylist.c b/plugins/gtkui/gtkplaylist.c new file mode 100644 index 00000000..cef45ea4 --- /dev/null +++ b/plugins/gtkui/gtkplaylist.c @@ -0,0 +1,2038 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> +#include <math.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <ctype.h> +#include <assert.h> +#include <sys/time.h> +#include "gtkplaylist.h" +#include "callbacks.h" +#include "interface.h" +#include "support.h" +#include "playlist.h" +#include "playback.h" +#include "codec.h" +#include "common.h" +#include "messagepump.h" +#include "streamer.h" +#include "search.h" +#include "progress.h" +#include "drawing.h" +#include "session.h" +#include "deadbeef.h" +#include "conf.h" +#include "timeline.h" + +//#define trace(...) { fprintf(stderr, __VA_ARGS__); } +#define trace(fmt,...) + +extern GtkWidget *mainwin; +extern GtkStatusIcon *trayicon; +extern gtkplaylist_t main_playlist; + +// orange on dark color scheme +float colo_dark_orange[COLO_COUNT][3] = { + { 0x7f/255.f, 0x7f/255.f, 0x7f/255.f }, // cursor + { 0x1d/255.f, 0x1f/255.f, 0x1b/255.f }, // odd + { 0x21/255.f, 0x23/255.f, 0x1f/255.f }, // even + { 0xaf/255.f, 0xa7/255.f, 0x9e/255.f }, // sel odd + { 0xa7/255.f, 0x9f/255.f, 0x96/255.f }, // sel even + { 0xf4/255.f, 0x7e/255.f, 0x46/255.f }, // text + { 0, 0, 0 }, // sel text + { 0x1d/255.f, 0x1f/255.f, 0x1b/255.f }, // seekbar back + { 0xf4/255.f, 0x7e/255.f, 0x46/255.f }, // seekbar front + { 0x1d/255.f, 0x1f/255.f, 0x1b/255.f }, // volumebar back + { 0xf4/255.f, 0x7e/255.f, 0x46/255.f }, // volumebar front + { 0xf4/255.f, 0x7e/255.f, 0x46/255.f }, // dragdrop marker +}; + +float colo_white_blue[COLO_COUNT][3] = { + { 0x7f/255.f, 0x7f/255.f, 0x7f/255.f }, // cursor + { 1, 1, 1 }, // odd + { 0xea/255.f, 0xeb/255.f, 0xec/255.f }, // even + { 0x24/255.f, 0x89/255.f, 0xb8/255.f }, // sel odd + { 0x20/255.f, 0x85/255.f, 0xb4/255.f }, // sel even + { 0, 0, 0 }, // text + { 1, 1, 1 }, // sel text + { 0x1d/255.f, 0x1f/255.f, 0x1b/255.f }, // seekbar back + { 0x24/255.f, 0x89/255.f, 0xb8/255.f }, // seekbar front + { 0x1d/255.f, 0x1f/255.f, 0x1b/255.f }, // volumebar back + { 0x24/255.f, 0x89/255.f, 0xb8/255.f }, // volumebar front + { 0x09/255.f, 0x22/255.f, 0x3a/255.f }, // dragdrop marker +}; + +#define MIN_COLUMN_WIDTH 16 + +// current color scheme +float colo_current[COLO_COUNT][3]; + +// playlist row height +int rowheight = -1; + +// playlist scrolling during dragging +static int playlist_scroll_mode = 0; // 0=select, 1=dragndrop +static int playlist_scroll_pointer_y = -1; +static int playlist_scroll_direction = 0; +static int playlist_scroll_active = 0; +static struct timeval tm_prevscroll; +static float scroll_sleep_time = 0; + +static uintptr_t play16_pixbuf; +static uintptr_t pause16_pixbuf; +static uintptr_t buffering16_pixbuf; + +static GdkCursor* cursor_sz; +static GdkCursor* cursor_drag; +static int header_dragging = -1; +static int header_sizing = -1; +static int header_dragpt[2]; + +#define COLHDR_ANIM_TIME 0.2f + +typedef struct { + int c1; + int c2; + int x1, x2; + int dx1, dx2; + // animated values + int ax1, ax2; + timeline_t *timeline; + int anim_active; + gtkplaylist_t *pl; +} colhdr_animator_t; + +static colhdr_animator_t colhdr_anim; + +static gboolean +redraw_header (void *data) { + colhdr_animator_t *anim = (colhdr_animator_t *)data; + gtkpl_header_draw (anim->pl); + gtkpl_expose_header (anim->pl, 0, 0, anim->pl->header->allocation.width, anim->pl->header->allocation.height); + return FALSE; +} + +static int +colhdr_anim_cb (float _progress, int _last, void *_ctx) { + colhdr_animator_t *anim = (colhdr_animator_t *)_ctx; + anim->ax1 = anim->x1 + (float)(anim->dx1 - anim->x1) * _progress; + anim->ax2 = anim->x2 + (float)(anim->dx2 - anim->x2) * _progress; +// printf ("%f %d %d\n", _progress, anim->ax1, anim->ax2); + g_idle_add (redraw_header, anim); + if (_last) { + anim->anim_active = 0; + } + return 0; +} + +static void +colhdr_anim_swap (gtkplaylist_t *pl, int c1, int c2, int x1, int x2) { + // interrupt previous anim + if (!colhdr_anim.timeline) { + colhdr_anim.timeline = timeline_create (); + } + colhdr_anim.pl = pl; + + colhdr_anim.c1 = c1; + colhdr_anim.c2 = c2; + + // find c1 and c2 in column list and setup coords + // note: columns are already swapped, so their coords must be reversed, + // as if before swap + gtkpl_column_t *c; + int idx = 0; + int x = 0; + for (c = pl->columns; c; c = c->next, idx++) { + if (idx == c1) { + colhdr_anim.x1 = x1; + colhdr_anim.dx2 = x; + } + else if (idx == c2) { + colhdr_anim.x2 = x2; + colhdr_anim.dx1 = x; + } + x += c->width; + } + colhdr_anim.anim_active = 1; + timeline_stop (colhdr_anim.timeline, 0); + timeline_init (colhdr_anim.timeline, COLHDR_ANIM_TIME, 100, colhdr_anim_cb, &colhdr_anim); + timeline_start (colhdr_anim.timeline); +} + +// that must be called before gtk_init +void +gtkpl_init (void) { + //memcpy (colo_current, colo_system_gtk, sizeof (colo_current)); + //memcpy (colo_current, colo_dark_orange, sizeof (colo_current)); + play16_pixbuf = draw_load_pixbuf ("play_16.png"); + pause16_pixbuf = draw_load_pixbuf ("pause_16.png"); + buffering16_pixbuf = draw_load_pixbuf ("buffering_16.png"); + rowheight = draw_get_font_size () + 12; + memcpy (colo_current, colo_white_blue, sizeof (colo_current)); +} + +void +gtkpl_free (gtkplaylist_t *pl) { + if (colhdr_anim.timeline) { + timeline_free (colhdr_anim.timeline, 1); + colhdr_anim.timeline = 0; + } + while (pl->columns) { + gtkpl_column_t *next = pl->columns->next; + gtkpl_column_free (pl->columns); + pl->columns = next; + } +} + +void +theme_set_cairo_source_rgb (cairo_t *cr, int col) { + cairo_set_source_rgb (cr, colo_current[col][0], colo_current[col][1], colo_current[col][2]); +} + +void +theme_set_fg_color (int col) { + draw_set_fg_color (colo_current[col]); +} + +void +theme_set_bg_color (int col) { + draw_set_bg_color (colo_current[col]); +} + +void +gtkpl_setup_scrollbar (gtkplaylist_t *ps) { + GtkWidget *playlist = ps->playlist; + int h = playlist->allocation.height / rowheight; + int size = (*ps->pcount); + if (h >= size) { + size = 0; + } + GtkWidget *scroll = ps->scrollbar; + if (ps->row >= (*ps->pcount)) { + ps->row = (*ps->pcount) - 1; + } + if (ps->scrollpos > (*ps->pcount)-ps->nvisiblerows+1) { + int n = (*ps->pcount) - ps->nvisiblerows + 1; + ps->scrollpos = max (0, n); + gtk_range_set_value (GTK_RANGE (scroll), ps->scrollpos); + } + if (size == 0) { + gtk_widget_hide (scroll); + } + else { + GtkAdjustment *adj = (GtkAdjustment*)gtk_adjustment_new (gtk_range_get_value (GTK_RANGE (scroll)), 0, size, 1, h, h); + gtk_range_set_adjustment (GTK_RANGE (scroll), adj); + gtk_widget_show (scroll); + } +} + +void +gtkpl_setup_hscrollbar (gtkplaylist_t *ps) { + GtkWidget *playlist = ps->playlist; + int w = playlist->allocation.width; + int size = 0; + int i; + gtkpl_column_t *c; + for (c = ps->columns; c; c = c->next) { + size += c->width; + } + if (w >= size) { + size = 0; + } + GtkWidget *scroll = ps->hscrollbar; + if (ps->hscrollpos >= size-w) { + int n = size-w-1; + ps->hscrollpos = max (0, n); + gtk_range_set_value (GTK_RANGE (scroll), ps->hscrollpos); + } + if (size == 0) { + gtk_widget_hide (scroll); + } + else { + GtkAdjustment *adj = (GtkAdjustment*)gtk_adjustment_new (gtk_range_get_value (GTK_RANGE (scroll)), 0, size, 1, w, w); + gtk_range_set_adjustment (GTK_RANGE (scroll), adj); + gtk_widget_show (scroll); + } +} + +void +gtkpl_redraw_pl_row_novis (gtkplaylist_t *ps, int row, playItem_t *it) { + draw_begin ((uintptr_t)ps->backbuf); + gtkpl_draw_pl_row_back (ps, row, it); + if (it) { + gtkpl_draw_pl_row (ps, row, it); + } + draw_end (); +} + +void +gtkpl_redraw_pl_row (gtkplaylist_t *ps, int row, playItem_t *it) { + int x, y, w, h; + GtkWidget *widget = ps->playlist; + x = 0; + y = (row - ps->scrollpos) * rowheight; + w = widget->allocation.width; + h = rowheight; + + gtkpl_redraw_pl_row_novis (ps, row, it); + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, x, y, x, y, w, h); +} + +void +gtkpl_draw_pl_row_back (gtkplaylist_t *ps, int row, playItem_t *it) { + // draw background + float w; + int start, end; + int startx, endx; + int width, height; + draw_get_canvas_size ((uintptr_t)ps->backbuf, &width, &height); + w = width; + if (it && ((it->selected && ps->multisel) || (row == ps->row && !ps->multisel))) { + if (row % 2) { + theme_set_fg_color (COLO_PLAYLIST_SEL_EVEN); + } + else { + theme_set_fg_color (COLO_PLAYLIST_SEL_ODD); + } + draw_rect (0, row * rowheight - ps->scrollpos * rowheight, width, rowheight, 1); + } + else { + if (row % 2) { + theme_set_fg_color (COLO_PLAYLIST_EVEN); + } + else { + theme_set_fg_color (COLO_PLAYLIST_ODD); + } + draw_rect (0, row * rowheight - ps->scrollpos * rowheight, width, rowheight, 1); + } + if (row == ps->row) { + theme_set_fg_color (COLO_PLAYLIST_CURSOR); + draw_rect (0, row * rowheight - ps->scrollpos * rowheight, width, rowheight-1, 0); + } +} + +void +gtkpl_draw_pl_row (gtkplaylist_t *ps, int row, playItem_t *it) { + if (row-ps->scrollpos >= ps->nvisiblerows || row-ps->scrollpos < 0) { +// fprintf (stderr, "WARNING: attempt to draw row outside of screen bounds (%d)\n", row-ps->scrollpos); + return; + } + int width, height; + draw_get_canvas_size ((uintptr_t)ps->backbuf, &width, &height); + if (it && ((it->selected && ps->multisel) || (row == ps->row && !ps->multisel))) { + if (row % 2) { + theme_set_bg_color (COLO_PLAYLIST_SEL_EVEN); + } + else { + theme_set_bg_color (COLO_PLAYLIST_SEL_ODD); + } + theme_set_fg_color (COLO_PLAYLIST_SEL_TEXT); + } + else { + if (row % 2) { + theme_set_bg_color (COLO_PLAYLIST_EVEN); + } + else { + theme_set_bg_color (COLO_PLAYLIST_ODD); + } + theme_set_fg_color (COLO_PLAYLIST_TEXT); + } + // draw as columns + char dur[50]; + pl_format_title (it, dur, sizeof (dur), "%l"); + + const char *artist = pl_find_meta (it, "artist"); + if (!artist) { + artist = "?"; + } + const char *album = pl_find_meta (it, "album"); + if (!album) { + album = "?"; + } + const char *track = pl_find_meta (it, "track"); + if (!track) { + track = ""; + } + const char *title = pl_find_meta (it, "title"); + if (!title) { + title = "?"; + } + char artistalbum[1024]; + pl_format_title (it, artistalbum, sizeof (artistalbum), "%a - %b"); +#if 0 + const char *columns[pl_ncolumns] = { + "", + artistalbum, + track, + title, + dur + }; +#endif + int x = -ps->hscrollpos; + gtkpl_column_t *c; + for (c = ps->columns; c; c = c->next) { + if (it == playlist_current_ptr && c->id == DB_COLUMN_PLAYING/* && !p_isstopped ()*/) { + int paused = p_ispaused (); + int buffering = !streamer_ok_to_read (-1); + uintptr_t pixbuf; + if (paused) { + pixbuf = pause16_pixbuf; + } + else if (!buffering) { + pixbuf = play16_pixbuf; + } + else { + pixbuf = buffering16_pixbuf; + } + draw_pixbuf ((uintptr_t)ps->backbuf, pixbuf, x + c->width/2 - 8 - ps->hscrollpos, (row - ps->scrollpos) * rowheight + rowheight/2 - 8, 0, 0, 16, 16); + } + else { + char fmt_text[1024]; + const char *text = NULL; + if (c->id != -1) { + switch (c->id) { + case DB_COLUMN_ARTIST_ALBUM: + text = artistalbum; + break; + case DB_COLUMN_ARTIST: + text = artist; + break; + case DB_COLUMN_ALBUM: + text = album; + break; + case DB_COLUMN_TITLE: + text = title; + break; + case DB_COLUMN_DURATION: + text = dur; + break; + case DB_COLUMN_TRACK: + text = track; + break; + } + } + else if (c->format) { + pl_format_title (it, fmt_text, sizeof (fmt_text), c->format); + text = fmt_text; + } + if (text) { + if (c->align_right) { + draw_text_with_colors (x+5, row * rowheight - ps->scrollpos * rowheight + rowheight/2 - draw_get_font_size ()/2 - 2, c->width-10, 1, text); + } + else { + draw_text_with_colors (x + 5, row * rowheight - ps->scrollpos * rowheight + rowheight/2 - draw_get_font_size ()/2 - 2, c->width-10, 0, text); + } + } + } + x += c->width; + } +} + + +void +gtkpl_draw_playlist (gtkplaylist_t *ps, int x, int y, int w, int h) { + GtkWidget *widget = ps->playlist; + if (!ps->backbuf) { + return; + } + draw_begin ((uintptr_t)ps->backbuf); + int row; + int row1; + int row2; + int row2_full; + row1 = max (0, y / rowheight + ps->scrollpos); + row2 = min ((*ps->pcount), (y+h) / rowheight + ps->scrollpos + 1); + row2_full = (y+h) / rowheight + ps->scrollpos + 1; + // draw background + playItem_t *it = gtkpl_get_for_idx (ps, ps->scrollpos); + playItem_t *it_copy = it; + for (row = row1; row < row2_full; row++) { + gtkpl_draw_pl_row_back (ps, row, it); + if (it) { + it = it->next[ps->iterator]; + } + } + it = it_copy; + int idx = 0; + for (row = row1; row < row2; row++, idx++) { + gtkpl_draw_pl_row (ps, row, it); + it = it->next[ps->iterator]; + } + + draw_end (); +} + +void +gtkpl_configure (gtkplaylist_t *ps) { + gtkpl_setup_scrollbar (ps); + gtkpl_setup_hscrollbar (ps); + GtkWidget *widget = ps->playlist; + if (ps->backbuf) { + g_object_unref (ps->backbuf); + ps->backbuf = NULL; + } + ps->nvisiblerows = ceil (widget->allocation.height / (float)rowheight); + ps->nvisiblefullrows = floor (widget->allocation.height / (float)rowheight); + ps->backbuf = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1); + + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); +} + +// change properties +gboolean +on_playlist_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data) +{ +// extern void main_playlist_init (GtkWidget *widget); +// main_playlist_init (widget); + GTKPL_PROLOGUE; + gtkpl_configure (ps); + return FALSE; +} + +void +gtkpl_expose (gtkplaylist_t *ps, int x, int y, int w, int h) { + GtkWidget *widget = ps->playlist; + if (widget->window) { + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, x, y, x, y, w, h); + } +} + +void +gtkpl_expose_header (gtkplaylist_t *ps, int x, int y, int w, int h) { + GtkWidget *widget = ps->header; + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf_header, x, y, x, y, w, h); +} + +void +gtkpl_select_single (gtkplaylist_t *ps, int sel) { + if (!ps->multisel) { + return; + } + int idx=0; + GtkWidget *widget = ps->playlist; + for (playItem_t *it = playlist_head[ps->iterator]; it; it = it->next[ps->iterator], idx++) { + if (idx == sel) { + if (!it->selected) { + it->selected = 1; + gtkpl_redraw_pl_row (ps, idx, it); + } + } + else if (it->selected) { + it->selected = 0; + gtkpl_redraw_pl_row (ps, idx, it); + } + } +} + +// {{{ expected behaviour for mouse1 without modifiers: +// {{{ [+] if clicked unselected item: +// unselect all +// select clicked item +// ps->row = clicked +// redraw +// start 'area selection' mode +// }}} +// {{{ [+] if clicked selected item: +// ps->row = clicked +// redraw +// wait until next release or motion event, whichever is 1st +// if release is 1st: +// unselect all except clicked, redraw +// else if motion is 1st: +// enter drag-drop mode +// }}} +// }}} +static int areaselect = 0; +static int areaselect_x = -1; +static int areaselect_y = -1; +static int areaselect_dx = -1; +static int areaselect_dy = -1; +static int dragwait = 0; +static int shift_sel_anchor = -1; + +void +gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time) { + // cursor must be set here, but selection must be handled in keyrelease + if ((*ps->pcount) == 0) { + return; + } + GtkWidget *widget = ps->playlist; + // remember mouse coords for doubleclick detection + ps->lastpos[0] = ex; + ps->lastpos[1] = ey; + // select item + int y = ey/rowheight + ps->scrollpos; + if (y < 0 || y >= (*ps->pcount)) { + y = -1; + } + + if (time - ps->clicktime < 0.5 + && fabs(ps->lastpos[0] - ex) < 3 + && fabs(ps->lastpos[1] - ey) < 3) { + // doubleclick - play this item + if (ps->row != -1) { + playItem_t *it = gtkpl_get_for_idx (ps, ps->row); + it->selected = 1; + int r = pl_get_idx_of (it); + int prev = main_playlist.row; + if (prev != r) { + main_playlist.row = r; + if (prev != -1) { + gtkpl_redraw_pl_row (&main_playlist, prev, pl_get_for_idx (prev)); + } + if (r != -1) { + gtkpl_redraw_pl_row (&main_playlist, r, it); + } + } + messagepump_push (M_PLAYSONGNUM, 0, r, 0); + return; + } + + // prevent next click to trigger doubleclick + ps->clicktime = time-1; + } + else { + ps->clicktime = time; + } + + int sel = y; + if (y == -1) { + y = (*ps->pcount) - 1; + } + int prev = ps->row; + ps->row = y; + shift_sel_anchor = ps->row; + // handle multiple selection + if (ps->multisel) { + if (!(state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK))) + { + playItem_t *it = gtkpl_get_for_idx (ps, sel); + if (!it || !it->selected) { + // reset selection, and set it to single item + gtkpl_select_single (ps, sel); + areaselect = 1; + areaselect_x = ex; + areaselect_y = ey; + areaselect_dx = -1; + areaselect_dy = -1; + shift_sel_anchor = ps->row; + } + else { + dragwait = 1; + gtkpl_redraw_pl_row (ps, prev, gtkpl_get_for_idx (ps, prev)); + if (ps->row != prev) { + gtkpl_redraw_pl_row (ps, ps->row, gtkpl_get_for_idx (ps, ps->row)); + } + } + } + else if (state & GDK_CONTROL_MASK) { + // toggle selection + if (y != -1) { + playItem_t *it = gtkpl_get_for_idx (ps, y); + if (it) { + it->selected = 1 - it->selected; + gtkpl_redraw_pl_row (ps, y, it); + } + } + } + else if (state & GDK_SHIFT_MASK) { + // select range + int start = min (prev, ps->row); + int end = max (prev, ps->row); + int idx = 0; + for (playItem_t *it = playlist_head[ps->iterator]; it; it = it->next[ps->iterator], idx++) { + if (idx >= start && idx <= end) { + if (!it->selected) { + it->selected = 1; + gtkpl_redraw_pl_row (ps, idx, it); + } + } + else { + if (it->selected) { + it->selected = 0; + gtkpl_redraw_pl_row (ps, idx, it); + } + } + } + } + if (ps->row != -1 && sel == -1) { + gtkpl_redraw_pl_row (ps, ps->row, gtkpl_get_for_idx (ps, ps->row)); + } + } + else { + if (ps->row != -1) { + gtkpl_redraw_pl_row (ps, ps->row, gtkpl_get_for_idx (ps, ps->row)); + } + } + if (prev != -1 && prev != ps->row) { + gtkpl_redraw_pl_row (ps, prev, gtkpl_get_for_idx (ps, prev)); + } + +} + +void +gtkpl_mouse1_released (gtkplaylist_t *ps, int state, int ex, int ey, double time) { + if (dragwait) { + dragwait = 0; + int y = ey/rowheight + ps->scrollpos; + gtkpl_select_single (ps, y); + } + else if (areaselect) { + playlist_scroll_direction = 0; + playlist_scroll_pointer_y = -1; + areaselect = 0; + } +} + +#if 0 +void +gtkpl_draw_areasel (GtkWidget *widget, int x, int y) { + // erase previous rect using 4 blits from ps->backbuffer + if (areaselect_dx != -1) { + int sx = min (areaselect_x, areaselect_dx); + int sy = min (areaselect_y, areaselect_dy); + int dx = max (areaselect_x, areaselect_dx); + int dy = max (areaselect_y, areaselect_dy); + int w = dx - sx + 1; + int h = dy - sy + 1; + //gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, sx, sy, sx, sy, dx - sx + 1, dy - sy + 1); + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, sx, sy, sx, sy, w, 1); + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, sx, sy, sx, sy, 1, h); + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, sx, sy + h - 1, sx, sy + h - 1, w, 1); + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, sx + w - 1, sy, sx + w - 1, sy, 1, h); + } + areaselect_dx = x; + areaselect_dy = y; + cairo_t *cr; + cr = gdk_cairo_create (widget->window); + if (!cr) { + return; + } + theme_set_fg_color (COLO_PLAYLIST_CURSOR); + cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); + cairo_set_line_width (cr, 1); + int sx = min (areaselect_x, x); + int sy = min (areaselect_y, y); + int dx = max (areaselect_x, x); + int dy = max (areaselect_y, y); + cairo_rectangle (cr, sx, sy, dx-sx, dy-sy); + cairo_stroke (cr); + gtkpl_cairo_destroy (cr); +} +#endif + +static gboolean +gtkpl_scroll_playlist_cb (gpointer data) { + gtkplaylist_t *ps = (gtkplaylist_t *)data; + playlist_scroll_active = 1; + struct timeval tm; + gettimeofday (&tm, NULL); + if (tm.tv_sec - tm_prevscroll.tv_sec + (tm.tv_usec - tm_prevscroll.tv_usec) / 1000000.0 < scroll_sleep_time) { + return TRUE; + } + memcpy (&tm_prevscroll, &tm, sizeof (tm)); + if (playlist_scroll_pointer_y == -1) { + playlist_scroll_active = 0; + return FALSE; + } + if (playlist_scroll_direction == 0) { + playlist_scroll_active = 0; + return FALSE; + } + int sc = ps->scrollpos + playlist_scroll_direction; + if (sc < 0) { + playlist_scroll_active = 0; + return FALSE; + } + if (sc >= *ps->pcount) { + playlist_scroll_active = 0; + return FALSE; + } + GDK_THREADS_ENTER (); + gtk_range_set_value (GTK_RANGE (ps->scrollbar), sc); + if (playlist_scroll_mode == 0) { + GdkEventMotion ev; + ev.y = playlist_scroll_pointer_y; + gtkpl_mousemove (ps, &ev); + } + else if (playlist_scroll_mode == 1) { + gtkpl_track_dragdrop (ps, playlist_scroll_pointer_y); + } + GDK_THREADS_LEAVE (); + scroll_sleep_time -= 0.1; + if (scroll_sleep_time < 0.05) { + scroll_sleep_time = 0.05; + } + return TRUE; +} + +void +gtkpl_mousemove (gtkplaylist_t *ps, GdkEventMotion *event) { + if (dragwait) { + GtkWidget *widget = ps->playlist; + if (gtk_drag_check_threshold (widget, ps->lastpos[0], event->x, ps->lastpos[1], event->y)) { + dragwait = 0; + GtkTargetEntry entry = { + .target = "STRING", + .flags = GTK_TARGET_SAME_WIDGET, + .info = TARGET_SAMEWIDGET + }; + GtkTargetList *lst = gtk_target_list_new (&entry, 1); + gtk_drag_begin (widget, lst, GDK_ACTION_MOVE, TARGET_SAMEWIDGET, (GdkEvent *)event); + } + } + else if (areaselect) { + GtkWidget *widget = ps->playlist; + int y = event->y/rowheight + ps->scrollpos; + //if (y != shift_sel_anchor) + { + int start = min (y, shift_sel_anchor); + int end = max (y, shift_sel_anchor); + int idx=0; + for (playItem_t *it = playlist_head[ps->iterator]; it; it = it->next[ps->iterator], idx++) { + if (idx >= start && idx <= end) { + if (!it->selected) { + it->selected = 1; + gtkpl_redraw_pl_row (ps, idx, it); + } + } + else if (it->selected) { + it->selected = 0; + gtkpl_redraw_pl_row (ps, idx, it); + } + } + } + + if (event->y < 10) { + playlist_scroll_mode = 0; + playlist_scroll_pointer_y = event->y; + playlist_scroll_direction = -1; + // start scrolling up + if (!playlist_scroll_active) { + scroll_sleep_time = 0.2; + gettimeofday (&tm_prevscroll, NULL); + g_idle_add (gtkpl_scroll_playlist_cb, ps); + } + } + else if (event->y > ps->playlist->allocation.height-10) { + playlist_scroll_mode = 0; + playlist_scroll_pointer_y = event->y; + playlist_scroll_direction = 1; + // start scrolling up + if (!playlist_scroll_active) { + scroll_sleep_time = 0.2; + gettimeofday (&tm_prevscroll, NULL); + g_idle_add (gtkpl_scroll_playlist_cb, ps); + } + } + else { + playlist_scroll_direction = 0; + playlist_scroll_pointer_y = -1; + } + // debug only + // gtkpl_draw_areasel (widget, event->x, event->y); + } +} + +void +gtkpl_handle_scroll_event (gtkplaylist_t *ps, int direction) { + GtkWidget *range = ps->scrollbar;; + GtkWidget *playlist = ps->playlist; + int h = playlist->allocation.height / rowheight; + int size = (*ps->pcount); + if (h >= size) { + size = 0; + } + if (size == 0) { + return; + } + // pass event to scrollbar + GtkAdjustment* adj = gtk_range_get_adjustment (GTK_RANGE (range)); + int newscroll = gtk_range_get_value (GTK_RANGE (range)); + if (direction == GDK_SCROLL_UP) { + newscroll -= 2; + } + else if (direction == GDK_SCROLL_DOWN) { + newscroll += 2; + } + gtk_range_set_value (GTK_RANGE (range), newscroll); +} + +void +gtkpl_scroll (gtkplaylist_t *ps, int newscroll) { + if (newscroll != ps->scrollpos) { + GtkWidget *widget = ps->playlist; + int di = newscroll - ps->scrollpos; + int d = abs (di); + if (d < ps->nvisiblerows) { + if (di > 0) { + gdk_draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, d * rowheight, 0, 0, widget->allocation.width, widget->allocation.height-d * rowheight); + int i; + ps->scrollpos = newscroll; + int start = ps->nvisiblerows-d-1; + start = max (0, ps->nvisiblerows-d-1); + for (i = start; i <= ps->nvisiblerows; i++) { + gtkpl_redraw_pl_row_novis (ps, i+ps->scrollpos, gtkpl_get_for_idx (ps, i+ps->scrollpos)); + } + } + else { + gdk_draw_drawable (ps->backbuf, widget->style->black_gc, ps->backbuf, 0, 0, 0, d*rowheight, widget->allocation.width, widget->allocation.height); + ps->scrollpos = newscroll; + int i; + for (i = 0; i <= d+1; i++) { + gtkpl_redraw_pl_row_novis (ps, i+ps->scrollpos, gtkpl_get_for_idx (ps, i+ps->scrollpos)); + } + } + } + else { + ps->scrollpos = newscroll; + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + } + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height); + } +} + +void +gtkpl_hscroll (gtkplaylist_t *ps, int newscroll) { + if (newscroll != ps->hscrollpos) { + ps->hscrollpos = newscroll; + GtkWidget *widget = ps->playlist; + gtkpl_header_draw (ps); + gtkpl_expose_header (ps, 0, 0, ps->header->allocation.width, ps->header->allocation.height); + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height); + } +} + +void +gtkpl_randomsong (void) { + p_stop (); + pl_randomsong (); +} + +void +gtkpl_playsongnum (int idx) { + p_stop (); + streamer_set_nextsong (idx, 1); +} + +void +gtkpl_songchanged (gtkplaylist_t *ps, int from, int to) { + if (!dragwait && to != -1) { + GtkWidget *widget = ps->playlist; + if (conf_get_int ("playlist.scroll.followplayback", 0)) { + if (to < ps->scrollpos || to >= ps->scrollpos + ps->nvisiblefullrows) { + gtk_range_set_value (GTK_RANGE (ps->scrollbar), to - ps->nvisiblerows/2); + } + } + } + + if (from >= 0) { + gtkpl_redraw_pl_row (ps, from, gtkpl_get_for_idx (ps, from)); + } + if (to >= 0) { + gtkpl_redraw_pl_row (ps, to, gtkpl_get_for_idx (ps, to)); + } +} + +void +gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state) { + GtkWidget *widget = ps->playlist; + GtkWidget *range = ps->scrollbar; + int prev = ps->row; + int newscroll = ps->scrollpos; +// C-f is now handled by gtk +// if ((keyval == GDK_F || keyval == GDK_f) && (state & GDK_CONTROL_MASK)) { +// search_start (); +// } +// else +// if ((keyval == GDK_A || keyval == GDK_a) && (state & GDK_CONTROL_MASK)) { +// // select all +// pl_select_all (); +// gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); +// gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height); +// return; +// } +// else if ((keyval == GDK_P || keyval == GDK_p) && (state & GDK_CONTROL_MASK)) { +// messagepump_push (M_PAUSESONG, 0, 0, 0); +// } +// else +// if (keyval == GDK_Return && ps->row != -1) { +// messagepump_push (M_PLAYSONGNUM, 0, ps->row, 0); +// return; +// } +// else +// if (keyval == GDK_Delete) { +// pl_delete_selected (); +// playlist_refresh (); +// return; +// } +// else + if (keyval == GDK_Down && ps->row < (*ps->pcount) - 1) { + ps->row++; + if (ps->row > ps->scrollpos + widget->allocation.height / rowheight - 1) { + newscroll = ps->row - widget->allocation.height / rowheight + 1; + } + } + else if (keyval == GDK_r) { + extern int replaygain; + replaygain = 1-replaygain; + fprintf (stderr, "replaygain=%d\n", replaygain); + } + else if (keyval == GDK_t) { + extern int replaygain_scale; + replaygain_scale = 1-replaygain_scale; + fprintf (stderr, "replaygain_scale=%d\n", replaygain_scale); + } + else if (keyval == GDK_Up && ps->row > 0) { + ps->row--; + if (ps->row < ps->scrollpos) { + newscroll = ps->row; + } + } + else if (keyval == GDK_Page_Down && ps->row < (*ps->pcount) - 1) { + ps->row += 10; + if (ps->row >= (*ps->pcount)) { + ps->row = (*ps->pcount) - 1; + } + if (ps->row > ps->scrollpos + widget->allocation.height / rowheight - 1) { + newscroll = ps->row - widget->allocation.height / rowheight + 1; + } + } + else if (keyval == GDK_Page_Up && ps->row > 0) { + ps->row -= 10; + if (ps->row < 0) { + ps->row = 0; + } + if (ps->row < ps->scrollpos) { + newscroll = ps->row; + } + } + else if (keyval == GDK_End && ps->row != (*ps->pcount) - 1) { + ps->row = (*ps->pcount) - 1; + if (ps->row > ps->scrollpos + widget->allocation.height / rowheight - 1) { + newscroll = ps->row - widget->allocation.height / rowheight + 1; + } + } + else if (keyval == GDK_Home && ps->row != 0) { + ps->row = 0; + if (ps->row < ps->scrollpos) { + newscroll = ps->row; + } + } + if (state & GDK_SHIFT_MASK) { + // select all between shift_sel_anchor and ps->row + if (prev != ps->row) { + int minvis = ps->scrollpos; + int maxvis = ps->scrollpos + ps->nvisiblerows-1; + int start = min (ps->row, shift_sel_anchor); + int end = max (ps->row, shift_sel_anchor); + int idx=0; + for (playItem_t *it = playlist_head[ps->iterator]; it; it = it->next[ps->iterator], idx++) { + if (idx >= start && idx <= end) { + it->selected = 1; + if (idx >= minvis && idx <= maxvis) { + if (newscroll == ps->scrollpos) { + gtkpl_redraw_pl_row (ps, idx, it); + } + else { + gtkpl_redraw_pl_row_novis (ps, idx, it); + } + } + } + else if (it->selected) + { + it->selected = 0; + if (idx >= minvis && idx <= maxvis) { + if (newscroll == ps->scrollpos) { + gtkpl_redraw_pl_row (ps, idx, it); + } + else { + gtkpl_redraw_pl_row_novis (ps, idx, it); + } + } + } + } + } + } + else { + // reset selection, set new single cursor/selection + if (prev != ps->row) { + int minvis = ps->scrollpos; + int maxvis = ps->scrollpos + ps->nvisiblerows-1; + shift_sel_anchor = ps->row; + int idx=0; + for (playItem_t *it = playlist_head[ps->iterator]; it; it = it->next[ps->iterator], idx++) { + if (idx == ps->row) { + if (!it->selected) { + it->selected = 1; + if (idx >= minvis && idx <= maxvis) { + if (newscroll == ps->scrollpos) { + gtkpl_redraw_pl_row (ps, idx, it); + } + else { + gtkpl_redraw_pl_row_novis (ps, idx, it); + } + } + } + } + else if (it->selected) { + it->selected = 0; + if (idx >= minvis && idx <= maxvis) { + if (newscroll == ps->scrollpos) { + gtkpl_redraw_pl_row (ps, idx, it); + } + else { + gtkpl_redraw_pl_row_novis (ps, idx, it); + } + } + } + } + } + } + if (newscroll != ps->scrollpos) { + gtk_range_set_value (GTK_RANGE (range), newscroll); + } +} + +static int drag_motion_y = -1; + +void +gtkpl_track_dragdrop (gtkplaylist_t *ps, int y) { + GtkWidget *widget = ps->playlist; + if (drag_motion_y != -1) { + // erase previous track + gdk_draw_drawable (widget->window, widget->style->black_gc, ps->backbuf, 0, drag_motion_y * rowheight-3, 0, drag_motion_y * rowheight-3, widget->allocation.width, 7); + + } + if (y == -1) { + drag_motion_y = -1; + return; + } + draw_begin ((uintptr_t)widget->window); + drag_motion_y = y / rowheight; + + theme_set_fg_color (COLO_DRAGDROP_MARKER); + draw_rect (0, drag_motion_y * rowheight-1, widget->allocation.width, 3, 1); + draw_rect (0, drag_motion_y * rowheight-3, 3, 7, 1); + draw_rect (widget->allocation.width-3, drag_motion_y * rowheight-3, 3, 7, 1); + draw_end (); + if (y < 10) { + playlist_scroll_pointer_y = y; + playlist_scroll_direction = -1; + playlist_scroll_mode = 1; + // start scrolling up + if (!playlist_scroll_active) { + scroll_sleep_time = 0.2; + gettimeofday (&tm_prevscroll, NULL); + g_idle_add (gtkpl_scroll_playlist_cb, ps); + } + } + else if (y > ps->playlist->allocation.height-10) { + playlist_scroll_mode = 1; + playlist_scroll_pointer_y = y; + playlist_scroll_direction = 1; + // start scrolling up + if (!playlist_scroll_active) { + scroll_sleep_time = 0.2; + gettimeofday (&tm_prevscroll, NULL); + g_idle_add (gtkpl_scroll_playlist_cb, ps); + } + } + else { + playlist_scroll_direction = 0; + playlist_scroll_pointer_y = -1; + } +} + +void +gtkpl_handle_drag_drop (gtkplaylist_t *ps, int drop_y, uint32_t *d, int length) { + int drop_row = drop_y / rowheight + ps->scrollpos; + playItem_t *drop_before = gtkpl_get_for_idx (ps, drop_row); + while (drop_before && drop_before->selected) { + drop_before = drop_before->next[ps->iterator]; + } + // unlink items from playlist, and link together + playItem_t *head = NULL; + playItem_t *tail = NULL; + int processed = 0; + int idx = 0; + playItem_t *next = NULL; + for (playItem_t *it = playlist_head[ps->iterator]; it && processed < length; it = next, idx++) { + next = it->next[ps->iterator]; + if (idx == d[processed]) { + if (it->prev[ps->iterator]) { + it->prev[ps->iterator]->next[ps->iterator] = it->next[ps->iterator]; + } + else { + playlist_head[ps->iterator] = it->next[ps->iterator]; + } + if (it->next[ps->iterator]) { + it->next[ps->iterator]->prev[ps->iterator] = it->prev[ps->iterator]; + } + else { + playlist_tail[ps->iterator] = it->prev[ps->iterator]; + } + if (tail) { + tail->next[ps->iterator] = it; + it->prev[ps->iterator] = tail; + tail = it; + } + else { + head = tail = it; + it->prev[ps->iterator] = it->next[ps->iterator] = NULL; + } + processed++; + } + } + // find insertion point + playItem_t *drop_after = NULL; + if (drop_before) { + drop_after = drop_before->prev[ps->iterator]; + } + else { + drop_after = playlist_tail[ps->iterator]; + } + // insert in between + head->prev[ps->iterator] = drop_after; + if (drop_after) { + drop_after->next[ps->iterator] = head; + } + else { + playlist_head[ps->iterator] = head; + } + tail->next[ps->iterator] = drop_before; + if (drop_before) { + drop_before->prev[ps->iterator] = tail; + } + else { + playlist_tail[ps->iterator] = tail; + } +} + +void +on_playlist_drag_end (GtkWidget *widget, + GdkDragContext *drag_context, + gpointer user_data) +{ + GTKPL_PROLOGUE; + // invalidate entire cache - slow, but rare + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + gtkpl_expose (ps, 0, 0, widget->allocation.width, widget->allocation.height); + playlist_scroll_direction = 0; + playlist_scroll_pointer_y = -1; +} + +void +strcopy_special (char *dest, const char *src, int len) { + while (len > 0) { + if (*src == '%' && len >= 3) { + int charcode = 0; + int byte; + byte = tolower (src[2]); + if (byte >= '0' && byte <= '9') { + charcode = byte - '0'; + } + else if (byte >= 'a' && byte <= 'f') { + charcode = byte - 'a' + 10; + } + else { + charcode = '?'; + } + if (charcode != '?') { + byte = tolower (src[1]); + if (byte >= '0' && byte <= '9') { + charcode |= (byte - '0') << 4; + } + else if (byte >= 'a' && byte <= 'f') { + charcode |= (byte - 'a' + 10) << 4; + } + else { + charcode = '?'; + } + } + *dest = charcode; + dest++; + src += 3; + len -= 3; + continue; + } + else { + *dest++ = *src++; + len--; + } + } + *dest = 0; +} + +int +gtkpl_add_file_info_cb (playItem_t *it, void *data) { + if (progress_is_aborted ()) { + return -1; + } + GDK_THREADS_ENTER(); + progress_settext (it->fname); + GDK_THREADS_LEAVE(); +#if 0 + GtkEntry *e = (GtkEntry *)data; + GDK_THREADS_ENTER(); + gtk_entry_set_text (GTK_ENTRY (e), it->fname); + GDK_THREADS_LEAVE(); + usleep (100); + countdown = 10; +#endif + return 0; +} + +void +gtkpl_add_fm_dropped_files (gtkplaylist_t *ps, char *ptr, int length, int drop_y) { + GDK_THREADS_ENTER(); + progress_show (); + GDK_THREADS_LEAVE(); + + int drop_row = drop_y / rowheight + ps->scrollpos; + playItem_t *drop_before = gtkpl_get_for_idx (ps, drop_row); + playItem_t *after = NULL; + if (drop_before) { + after = drop_before->prev[ps->iterator]; + } + else { + after = playlist_tail[ps->iterator]; + } + const uint8_t *p = (const uint8_t*)ptr; + while (*p) { + const uint8_t *pe = p; + while (*pe && *pe > ' ') { + pe++; + } + if (pe - p < 4096 && pe - p > 7) { + char fname[(int)(pe - p)]; + strcopy_special (fname, p, pe-p); + //strncpy (fname, p, pe - p); + //fname[pe - p] = 0; + int abort = 0; + playItem_t *inserted = pl_insert_dir (after, fname, &abort, gtkpl_add_file_info_cb, NULL); + if (!inserted && !abort) { + inserted = pl_insert_file (after, fname, &abort, gtkpl_add_file_info_cb, NULL); + } + if (inserted) { + after = inserted; + } + } + p = pe; + // skip whitespace + while (*p && *p <= ' ') { + p++; + } + } + free (ptr); + + GDK_THREADS_ENTER(); + progress_hide (); + playlist_refresh (); + GDK_THREADS_LEAVE(); +} + +void +gtkpl_handle_fm_drag_drop (gtkplaylist_t *ps, int drop_y, void *ptr, int length) { + // this happens when dropped from file manager + char *mem = malloc (length+1); + memcpy (mem, ptr, length); + mem[length] = 0; + // we don't pass control structure, but there's only one drag-drop view currently + messagepump_push (M_FMDRAGDROP, (uintptr_t)mem, length, drop_y); +} + +void +gtkpl_header_draw (gtkplaylist_t *ps) { + GtkWidget *widget = ps->header; + int x = -ps->hscrollpos; + int w = 100; + int h = widget->allocation.height; + const char *detail = "toolbar"; + + // fill background + gtk_paint_box (widget->style, ps->backbuf_header, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, NULL, detail, 0, 0, widget->allocation.width, widget->allocation.height); + draw_begin ((uintptr_t)ps->backbuf_header); + x = -ps->hscrollpos; + gtkpl_column_t *c; + int need_draw_moving = 0; + int idx = 0; + for (c = ps->columns; c; c = c->next, idx++) { + w = c->width; + int xx = x; + if (colhdr_anim.anim_active) { + if (idx == colhdr_anim.c2) { + xx = colhdr_anim.ax1; + } + else if (idx == colhdr_anim.c1) { + xx = colhdr_anim.ax2; + } + } + if (header_dragging < 0 || idx != header_dragging) { + if (xx >= widget->allocation.width) { + continue; + } + if (w > 0) { + gtk_paint_vline (widget->style, ps->backbuf_header, GTK_STATE_NORMAL, NULL, NULL, NULL, 0, h, xx+w - 2); + GdkColor *gdkfg = &widget->style->fg[0]; + float fg[3] = {(float)gdkfg->red/0xffff, (float)gdkfg->green/0xffff, (float)gdkfg->blue/0xffff}; + draw_set_fg_color (fg); + draw_text (xx + 5, h/2-draw_get_font_size()/2, c->width-10, 0, c->title); + } + } + else { + need_draw_moving = 1; + } + x += w; + } + if (need_draw_moving) { + x = -ps->hscrollpos; + idx = 0; + for (c = ps->columns; c; c = c->next, idx++) { + w = c->width; + if (idx == header_dragging) { + if (colhdr_anim.anim_active) { + if (idx == colhdr_anim.c2) { + x = colhdr_anim.ax1; + } + else if (idx == colhdr_anim.c1) { + x = colhdr_anim.ax2; + } + } + // draw empty slot + if (x < widget->allocation.width) { + gtk_paint_box (widget->style, ps->backbuf_header, GTK_STATE_ACTIVE, GTK_SHADOW_ETCHED_IN, NULL, NULL, "button", x, 0, w, h); + } + x = c->movepos; + if (x >= widget->allocation.width) { + break; + } + if (w > 0) { + gtk_paint_box (widget->style, ps->backbuf_header, GTK_STATE_SELECTED, GTK_SHADOW_OUT, NULL, NULL, "button", x, 0, w, h); + GdkColor *gdkfg = &widget->style->fg[0]; + float fg[3] = {(float)gdkfg->red/0xffff, (float)gdkfg->green/0xffff, (float)gdkfg->blue/0xffff}; + draw_set_fg_color (fg); + draw_text (x + 5, h/2-draw_get_font_size()/2, c->width-10, 0, c->title); + } + break; + } + x += w; + } + } + draw_end (); +} + +gboolean +on_header_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + gtkpl_header_draw (ps); + gtkpl_expose_header (ps, event->area.x, event->area.y, event->area.width, event->area.height); + return FALSE; +} + + +gboolean +on_header_configure_event (GtkWidget *widget, + GdkEventConfigure *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + if (ps->backbuf_header) { + g_object_unref (ps->backbuf_header); + ps->backbuf_header = NULL; + } + ps->backbuf_header = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1); + gtkpl_header_draw (ps); + return FALSE; +} + + +void +on_header_realize (GtkWidget *widget, + gpointer user_data) +{ + // create cursor for sizing headers + int h = draw_get_font_size (); + gtk_widget_set_size_request (widget, -1, h + 10); + cursor_sz = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW); + cursor_drag = gdk_cursor_new (GDK_FLEUR); +} + +float last_header_motion_ev = -1; +int prev_header_x = -1; + +gboolean +on_header_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + if (header_dragging >= 0) { + gdk_window_set_cursor (widget->window, cursor_drag); + gtkpl_column_t *c; + int i; + for (i = 0, c = ps->columns; i < header_dragging && c; c = c->next, i++); + c->movepos = event->x - header_dragpt[0]; + + // find closest column to the left + int inspos = -1; + gtkpl_column_t *cc; + int x = 0; + int idx = 0; + int x1 = -1, x2 = -1; + for (cc = ps->columns; cc; cc = cc->next, idx++) { + if (x < c->movepos && x + c->width > c->movepos) { + inspos = idx; + x1 = x; + } + else if (idx == header_dragging) { + x2 = x; + } + x += cc->width; + } + if (inspos >= 0 && inspos != header_dragging) { + int c1 = inspos; + int c2 = header_dragging; + // remove c from list + if (c == ps->columns) { + ps->columns = c->next; + } + else { + for (cc = ps->columns; cc; cc = cc->next) { + if (cc->next == c) { + cc->next = c->next; + } + } + } + c->next = NULL; + // reinsert c at position inspos update header_dragging to new idx + header_dragging = inspos; + if (inspos == 0) { + c->next = ps->columns; + ps->columns = c; + } + else { + idx = 0; + gtkpl_column_t *prev = NULL; + for (cc = ps->columns; cc; cc = cc->next, idx++, prev = cc) { + if (idx+1 == inspos) { + gtkpl_column_t *next = cc->next; + cc->next = c; + c->next = next; + break; + } + } + } +// colhdr_anim_swap (ps, c1, c2, x1, x2); + // force redraw of everything +// gtkpl_setup_hscrollbar (ps); + gtkpl_draw_playlist (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + gtkpl_expose (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + gtkpl_column_update_config (ps, c, i); + } + else { + // only redraw that if not animating + gtkpl_header_draw (ps); + gtkpl_expose_header (ps, 0, 0, ps->header->allocation.width, ps->header->allocation.height); + } + } + else if (header_sizing >= 0) { + // limit event rate + if (event->time - last_header_motion_ev < 50 || prev_header_x == event->x) { + return FALSE; + } + last_header_motion_ev = event->time; + prev_header_x = event->x; + gdk_window_set_cursor (widget->window, cursor_sz); + // get column start pos + int x = -ps->hscrollpos; + int i = 0; + gtkpl_column_t *c; + for (c = ps->columns; c && i < header_sizing; c = c->next, i++) { + x += c->width; + } + + int newx = event->x > x + MIN_COLUMN_WIDTH ? event->x : x + MIN_COLUMN_WIDTH; + c->width = newx - x; + gtkpl_setup_hscrollbar (ps); + gtkpl_header_draw (ps); + gtkpl_expose_header (ps, 0, 0, ps->header->allocation.width, ps->header->allocation.height); + gtkpl_draw_playlist (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + gtkpl_expose (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + gtkpl_column_update_config (ps, c, i); + } + else { + int x = -ps->hscrollpos; + gtkpl_column_t *c; + for (c = ps->columns; c; c = c->next) { + int w = c->width; + if (w > 0) { // ignore collapsed columns (hack for search window) + if (event->x >= x + w - 2 && event->x <= x + w) { + gdk_window_set_cursor (widget->window, cursor_sz); + break; + } + else { + gdk_window_set_cursor (widget->window, NULL); + } + } + else { + gdk_window_set_cursor (widget->window, NULL); + } + x += w; + } + } + return FALSE; +} + +gboolean +on_header_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + if (event->button == 1) { + // start sizing/dragging + header_dragging = -1; + header_sizing = -1; + header_dragpt[0] = event->x; + header_dragpt[1] = event->y; + int x = -ps->hscrollpos; + int i = 0; + gtkpl_column_t *c; + for (c = ps->columns; c; c = c->next, i++) { + int w = c->width; + if (event->x >= x + w - 2 && event->x <= x + w) { + header_sizing = i; + header_dragging = -1; + break; + } + else if (event->x > x + 2 && event->x < x + w - 2) { + header_dragpt[0] = event->x - x; + header_dragging = i; + header_sizing = -1; + break; + } + x += w; + } + } + prev_header_x = -1; + last_header_motion_ev = -1; + return FALSE; +} + +gboolean +on_header_button_release_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GTKPL_PROLOGUE; + if (event->button == 1) { + header_sizing = -1; + int x = 0; + gtkpl_column_t *c; + for (c = ps->columns; c; c = c->next) { + int w = c->width; + if (event->x >= x + w - 2 && event->x <= x + w) { + gdk_window_set_cursor (widget->window, cursor_sz); + break; + } + else { + gdk_window_set_cursor (widget->window, NULL); + } + x += w; + } + if (header_dragging >= 0) { + header_dragging = -1; + gtkpl_setup_hscrollbar (ps); + gtkpl_header_draw (ps); + gtkpl_expose_header (ps, 0, 0, ps->header->allocation.width, ps->header->allocation.height); + gtkpl_draw_playlist (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + gtkpl_expose (ps, 0, 0, ps->playlist->allocation.width, ps->playlist->allocation.height); + gtkpl_column_rewrite_config (ps); + } + } +// NOTE: disabled for 0.3.0 release +// else if (event->button == 3) { +// GtkWidget *menu = create_headermenu (); +// gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, widget, 0, gtk_get_current_event_time()); +// } + return FALSE; +} + +void +gtkpl_add_dir (gtkplaylist_t *ps, char *folder) { + GDK_THREADS_ENTER(); + progress_show (); + GDK_THREADS_LEAVE(); + pl_add_dir (folder, gtkpl_add_file_info_cb, NULL); + g_free (folder); + GDK_THREADS_ENTER(); + progress_hide (); + playlist_refresh (); + GDK_THREADS_LEAVE(); +} + +static void +gtkpl_adddir_cb (gpointer data, gpointer userdata) { + pl_add_dir (data, gtkpl_add_file_info_cb, userdata); + g_free (data); +} + +void +gtkpl_add_dirs (gtkplaylist_t *ps, GSList *lst) { + GDK_THREADS_ENTER(); + progress_show (); + GDK_THREADS_LEAVE(); + g_slist_foreach(lst, gtkpl_adddir_cb, NULL); + g_slist_free (lst); + GDK_THREADS_ENTER(); + progress_hide (); + playlist_refresh (); + GDK_THREADS_LEAVE(); +} + +static void +gtkpl_addfile_cb (gpointer data, gpointer userdata) { + pl_add_file (data, gtkpl_add_file_info_cb, userdata); + g_free (data); +} + +void +gtkpl_add_files (gtkplaylist_t *ps, GSList *lst) { + GDK_THREADS_ENTER(); + progress_show (); + GDK_THREADS_LEAVE(); + g_slist_foreach(lst, gtkpl_addfile_cb, NULL); + g_slist_free (lst); + GDK_THREADS_ENTER(); + progress_hide (); + playlist_refresh (); + GDK_THREADS_LEAVE(); +} + +void +gtkpl_playsong (gtkplaylist_t *ps) { + if (p_ispaused ()) { + p_unpause (); + } + else if (ps->row != -1) { + p_stop (); + streamer_set_nextsong (ps->row, 1); + } + else { + p_stop (); + streamer_set_nextsong (0, 1); + } +} + +int +gtkpl_get_idx_of (gtkplaylist_t *ps, playItem_t *it) { + playItem_t *c = playlist_head[ps->iterator]; + int idx = 0; + while (c && c != it) { + c = c->next[ps->iterator]; + idx++; + } + if (!c) { + return -1; + } + return idx; +} + +playItem_t * +gtkpl_get_for_idx (gtkplaylist_t *ps, int idx) { + playItem_t *it = playlist_head[ps->iterator]; + while (idx--) { + if (!it) + return NULL; + it = it->next[ps->iterator]; + } + return it; +} + +void +playlist_refresh (void) { + extern gtkplaylist_t main_playlist; + gtkplaylist_t *ps = &main_playlist; + gtkpl_setup_scrollbar (ps); + GtkWidget *widget = ps->playlist; + gtkpl_draw_playlist (ps, 0, 0, widget->allocation.width, widget->allocation.height); + gtkpl_expose (ps, 0, 0, widget->allocation.width, widget->allocation.height); + search_refresh (); +} + +gtkpl_column_t * +gtkpl_column_alloc (const char *title, int width, int id, const char *format, int align_right) { + gtkpl_column_t *c = malloc (sizeof (gtkpl_column_t)); + memset (c, 0, sizeof (gtkpl_column_t)); + c->title = strdup (title); + c->id = id; + c->format = format ? strdup (format) : NULL; + c->width = width; + c->align_right = align_right; + return c; +} + +void +gtkpl_column_append (gtkplaylist_t *pl, gtkpl_column_t *c) { + int idx = 0; + if (pl->columns) { + idx++; + gtkpl_column_t *tail = pl->columns; + while (tail->next) { + tail = tail->next; + idx++; + } + tail->next = c; + } + else { + pl->columns = c; + } + gtkpl_column_update_config (pl, c, idx); +} + +void +gtkpl_column_free (gtkpl_column_t *c) { + if (c->title) { + free (c->title); + } + if (c->format) { + free (c->format); + } + free (c); +} + +void +gtkpl_column_remove (gtkplaylist_t *pl, gtkpl_column_t *c) { + if (pl->columns == c) { + pl->columns = pl->columns->next; + gtkpl_column_free (c); + return; + } + gtkpl_column_t *cc = pl->columns; + while (cc) { + if (cc->next == c) { + cc->next = cc->next->next; + gtkpl_column_free (c); + return; + } + cc = cc->next; + } + assert (cc && "gtkpl: attempted to remove column that is not in list"); +} + +void +gtkpl_append_column_from_textdef (gtkplaylist_t *pl, const uint8_t *def) { + // syntax: "title" "format" id width alignright + char title[128]; + char format[128]; + int id; + int width; + int align_right; + // title + if (*def != '"') { + return; + } + def++; + if (*def == 0) { + return; + } + const uint8_t *e = def; + e++; + while (*e && *e != '"') { + e++; + } + if (*e == 0) { + return; + } + memcpy (title, def, e-def); + title[e-def] = 0; + // skip whitespace + def = e; + def++; + while (*def && *def <= ' ') { + def++; + } + if (*def == 0) { + return; + } + // format + if (*def != '"') { + return; + } + def++; + if (*def == 0) { + return; + } + e = def; + while (*e && *e != '"') { + e++; + } + if (*e == 0) { + return; + } + memcpy (format, def, e-def); + format[e-def] = 0; + // skip whitespace + def = e; + def++; + while (*def && *def <= ' ') { + def++; + } + if (*def == 0) { + return; + } + // id + e = def; + while (*e && (isdigit (*e) || *e == '-')) { + e++; + } + if (*e == 0) { + return; + } + { + char s[e-def+1]; + memcpy (s, def, e-def); + s[e-def] = 0; + id = atoi (s); + } + // skip whitespace + def = e; + def++; + while (*def && *def <= ' ') { + def++; + } + if (*def == 0) { + return; + } + // width + e = def; + while (*e && isdigit (*e)) { + e++; + } + if (*e == 0) { + return; + } + { + char s[e-def+1]; + memcpy (s, def, e-def); + s[e-def] = 0; + width = atoi (s); + } + // skip whitespace + def = e; + def++; + while (*def && *def <= ' ') { + def++; + } + if (*def == 0) { + return; + } + // align_right + e = def; + while (*e && isdigit (*e)) { + e++; + } + { + char s[e-def+1]; + memcpy (s, def, e-def); + s[e-def] = 0; + align_right = atoi (s); + } + gtkpl_column_append (pl, gtkpl_column_alloc (title, width, id, format[0] ? format : NULL, align_right)); +} + +void +gtkpl_column_update_config (gtkplaylist_t *pl, gtkpl_column_t *c, int idx) { + char key[128]; + char value[128]; + snprintf (key, sizeof (key), "%s.column.%d", pl->title, idx); + snprintf (value, sizeof (value), "\"%s\" \"%s\" %d %d %d", c->title, c->format ? c->format : "", c->id, c->width, c->align_right); + conf_set_str (key, value); +} + +void +gtkpl_column_rewrite_config (gtkplaylist_t *pl) { + char key[128]; + char value[128]; + snprintf (key, sizeof (key), "%s.column.", pl->title); + conf_remove_items (key); + + gtkpl_column_t *c; + int i = 0; + for (c = pl->columns; c; c = c->next, i++) { + snprintf (key, sizeof (key), "%s.column.%d", pl->title, i); + snprintf (value, sizeof (value), "\"%s\" \"%s\" %d %d %d", c->title, c->format ? c->format : "", c->id, c->width, c->align_right); + conf_set_str (key, value); + } +} + +void +set_tray_tooltip (const char *text) { +#if (GTK_MINOR_VERSION < 16) + gtk_status_icon_set_tooltip (trayicon, text); +#else + gtk_status_icon_set_tooltip_text (trayicon, text); +#endif +} + +void +gtkpl_current_track_changed (playItem_t *it) { + char str[600]; + char dname[512]; + pl_format_item_display_name (it, dname, 512); + snprintf (str, 600, "DeaDBeeF - %s", dname); + gtk_window_set_title (GTK_WINDOW (mainwin), str); + set_tray_tooltip (str); +} + +void +gtkpl_songchanged_wrapper (int from, int to) { + GDK_THREADS_ENTER (); + // update window title + if (from >= 0 || to >= 0) { + if (to >= 0) { + playItem_t *it = pl_get_for_idx (to); + if (it) { // it might have been deleted after event was sent + gtkpl_current_track_changed (it); + } + } + else { + gtk_window_set_title (GTK_WINDOW (mainwin), "DeaDBeeF"); + set_tray_tooltip ("DeaDBeeF"); + } + } + // update playlist view + gtkpl_songchanged (&main_playlist, from, to); + GDK_THREADS_LEAVE (); +} diff --git a/plugins/gtkui/gtkplaylist.h b/plugins/gtkui/gtkplaylist.h new file mode 100644 index 00000000..2e827839 --- /dev/null +++ b/plugins/gtkui/gtkplaylist.h @@ -0,0 +1,261 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __GTKPLAYLIST_H +#define __GTKPLAYLIST_H + +#include <gtk/gtk.h> +#include <stdint.h> +#include <assert.h> +#include "playlist.h" + +// drag and drop targets +enum { + TARGET_URILIST, + TARGET_SAMEWIDGET, +}; + +// color scheme constants +enum { + COLO_PLAYLIST_CURSOR, + COLO_PLAYLIST_ODD, + COLO_PLAYLIST_EVEN, + COLO_PLAYLIST_SEL_ODD, + COLO_PLAYLIST_SEL_EVEN, + COLO_PLAYLIST_TEXT, + COLO_PLAYLIST_SEL_TEXT, + COLO_SEEKBAR_BACK, + COLO_SEEKBAR_FRONT, + COLO_VOLUMEBAR_BACK, + COLO_VOLUMEBAR_FRONT, + COLO_DRAGDROP_MARKER, + COLO_COUNT +}; + +//#define pl_ncolumns 5 +//#define pl_colname_max 100 + +typedef struct gtkpl_column_s { + char *title; + int id; // id is faster than format, set to -1 to use format + char *format; + int width; + int movepos; // valid only while `moving' is 1 + struct gtkpl_column_s *next; + unsigned align_right : 1; +// unsigned moving : 1; +} gtkpl_column_t; + +// structure of this kind must be set as user data for playlist, header and scrollbar widgets +// pointer to this structure must be passed too all functions that +// implement playlist functionality (like this pointer) +typedef struct { + // cached gtk/gdk object pointers + GtkWidget *playlist; + GtkWidget *header; + GtkWidget *scrollbar; + GtkWidget *hscrollbar; + GdkPixmap *backbuf; + GdkPixmap *backbuf_header; + const char *title; // unique id, used for config writing, etc + // parameters + playItem_t **pcurr; // pointer to current item + int *pcount; // pointer to count of items in list + int iterator; // index into next array of playItem_t struct + int lastpos[2]; // last mouse position (for playlist widget) + int multisel; // if it uses multiple selection + // current state + int scrollpos; + int hscrollpos; + int row; + double clicktime; // for doubleclick detection + int nvisiblerows; + int nvisiblefullrows; +// int *colwidths;//[pl_ncolumns]; // current column widths +// int ncolumns; + gtkpl_column_t *columns; +} gtkplaylist_t; + +#define GTKPL_PROLOGUE \ + gtkplaylist_t *ps = (gtkplaylist_t *)gtk_object_get_data (GTK_OBJECT (widget), "ps"); assert (ps); + +extern int rowheight; + +// that must be called before gtk_init +void +gtkpl_init (void); + +void +gtkpl_free (gtkplaylist_t *pl); + +void +gtkpl_redraw_pl_row (gtkplaylist_t *ps, int row, playItem_t *it); + +void +gtkpl_redraw_pl_row_novis (gtkplaylist_t *ps, int row, playItem_t *it); + +void +gtkpl_setup_scrollbar (gtkplaylist_t *ps); + +void +gtkpl_draw_pl_row_back (gtkplaylist_t *ps, int row, playItem_t *it); + +void +gtkpl_draw_pl_row (gtkplaylist_t *ps, int row, playItem_t *it); + +void +gtkpl_draw_playlist (gtkplaylist_t *ps, int x, int y, int w, int h); + +void +gtkpl_reconf (gtkplaylist_t *ps); + +void +gtkpl_expose (gtkplaylist_t *ps, int x, int y, int w, int h); + +void +gtkpl_mouse1_pressed (gtkplaylist_t *ps, int state, int ex, int ey, double time); + +void +gtkpl_mouse1_released (gtkplaylist_t *ps, int state, int ex, int ey, double time); + +void +gtkpl_mousemove (gtkplaylist_t *ps, GdkEventMotion *event); + +void +gtkpl_scroll (gtkplaylist_t *ps, int newscroll); + +void +gtkpl_hscroll (gtkplaylist_t *ps, int newscroll); + +void +gtkpl_handle_scroll_event (gtkplaylist_t *ps, int direction); + +void +gtkpl_keypress (gtkplaylist_t *ps, int keyval, int state); + +void +gtkpl_track_dragdrop (gtkplaylist_t *ps, int y); + +void +gtkpl_handle_drag_drop (gtkplaylist_t *ps, int drop_y, uint32_t *d, int length); + +void +gtkpl_handle_fm_drag_drop (gtkplaylist_t *ps, int drop_y, void *ptr, int length); + +void +gtkpl_add_fm_dropped_files (gtkplaylist_t *ps, char *ptr, int length, int drop_y); + +void +gtkpl_select_single (gtkplaylist_t *ps, int sel); + +void +gtkpl_header_draw (gtkplaylist_t *ps); + +void +gtkpl_add_dir (gtkplaylist_t *ps, char *folder); + +void +gtkpl_add_dirs (gtkplaylist_t *ps, GSList *lst); + +void +gtkpl_add_files (gtkplaylist_t *ps, GSList *lst); + +void +gtkpl_configure (gtkplaylist_t *ps); + +int +gtkpl_get_idx_of (gtkplaylist_t *ps, playItem_t *it); + +playItem_t * +gtkpl_get_for_idx (gtkplaylist_t *ps, int idx); + +// this functions take value from passed playlist, that's why it's here +void +gtkpl_playsong (gtkplaylist_t *ps); + +void +gtkpl_songchanged (gtkplaylist_t *ps, int from, int to); + +// these functions operate on global playlist level, +// no need to pass gtkplaylist_t ptr to them + +void +gtkpl_add_fm_dropped_files (gtkplaylist_t *ps, char *ptr, int length, int drop_y); + +// these functions should not belong here +void +gtkpl_prevsong (void); + +void +gtkpl_nextsong (void); + +void +gtkpl_randomsong (void); + +void +gtkpl_pausesong (void); + +void +gtkpl_playsongnum (int idx); + +void +theme_set_fg_color (int col); + +void +theme_set_bg_color (int col); + +void +theme_set_cairo_source_rgb (cairo_t *cr, int col); + +void +playlist_refresh (void); + +// column utilities +gtkpl_column_t * +gtkpl_column_alloc (const char *title, int width, int id, const char *format, int align_right); + +void +gtkpl_column_append (gtkplaylist_t *pl, gtkpl_column_t *c); + +void +gtkpl_column_remove (gtkplaylist_t *pl, gtkpl_column_t *c); + +void +gtkpl_column_free (gtkpl_column_t *c); + +void +gtkpl_append_column_from_textdef (gtkplaylist_t *pl, const uint8_t *def); + +void +gtkpl_column_update_config (gtkplaylist_t *pl, gtkpl_column_t *c, int idx); + +void +gtkpl_column_rewrite_config (gtkplaylist_t *pl); + +void +gtkpl_expose_header (gtkplaylist_t *ps, int x, int y, int w, int h); + +void +set_tray_tooltip (const char *text); + +void +gtkpl_songchanged_wrapper (int from, int to); + +void +gtkpl_current_track_changed (playItem_t *it); + +#endif // __GTKPLAYLIST_H diff --git a/plugins/gtkui/gtksession.c b/plugins/gtkui/gtksession.c new file mode 100644 index 00000000..e24706b6 --- /dev/null +++ b/plugins/gtkui/gtksession.c @@ -0,0 +1,44 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include <stdio.h> +#include <gtk/gtk.h> +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "session.h" +#include "conf.h" + +void +session_capture_window_attrs (uintptr_t window) { + GtkWindow *wnd = GTK_WINDOW (window); + int win_attrs[4]; + gtk_window_get_position (wnd, &win_attrs[0], &win_attrs[1]); + gtk_window_get_size (wnd, &win_attrs[2], &win_attrs[3]); + conf_set_int ("mainwin.geometry.x", win_attrs[0]); + conf_set_int ("mainwin.geometry.y", win_attrs[1]); + conf_set_int ("mainwin.geometry.w", win_attrs[2]); + conf_set_int ("mainwin.geometry.h", win_attrs[3]); +} + +void +session_restore_window_attrs (uintptr_t window) { + GtkWindow *wnd = GTK_WINDOW (window); + gtk_window_move (wnd, conf_get_int ("mainwin.geometry.x", 40), conf_get_int ("mainwin.geometry.y", 40)); + gtk_window_resize (wnd, conf_get_int ("mainwin.geometry.w", 500), conf_get_int ("mainwin.geometry.h", 300)); +} diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c new file mode 100644 index 00000000..c5a87056 --- /dev/null +++ b/plugins/gtkui/gtkui.c @@ -0,0 +1,343 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009 Alexey Yakovenko + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include "../../deadbeef.h" +#include <gtk/gtk.h> +#include "gtkplaylist.h" +#include "search.h" +#include "progress.h" +#include "interface.h" +#include "callbacks.h" +#include "support.h" + +// main widgets +GtkWidget *mainwin; +GtkWidget *searchwin; +GtkStatusIcon *trayicon; +GtkWidget *traymenu; + +// playlist configuration structures +gtkplaylist_t main_playlist; +gtkplaylist_t search_playlist; + +// update status bar and window title +static int sb_context_id = -1; +static char sb_text[512]; +static float last_songpos = -1; + +static void +update_songinfo (void) { + char sbtext_new[512] = "-"; + float songpos = last_songpos; + + int daystotal = (int)pl_totaltime / (3600*24); + int hourtotal = ((int)pl_totaltime / 3600) % 24; + int mintotal = ((int)pl_totaltime/60) % 60; + int sectotal = ((int)pl_totaltime) % 60; + + char totaltime_str[512] = ""; + if (daystotal == 0) + snprintf (totaltime_str, sizeof (totaltime_str), "%d:%02d:%02d", hourtotal, mintotal, sectotal); + + else if (daystotal == 1) + snprintf (totaltime_str, sizeof (totaltime_str), "1 day %d:%02d:%02d", hourtotal, mintotal, sectotal); + + else + snprintf (totaltime_str, sizeof (totaltime_str), "%d days %d:%02d:%02d", daystotal, hourtotal, mintotal, sectotal); + + if (p_isstopped ()) { + snprintf (sbtext_new, sizeof (sbtext_new), "Stopped | %s total playtime", totaltime_str); + songpos = 0; + } + else if (str_playing_song.decoder) { +// codec_lock (); + DB_decoder_t *c = str_playing_song.decoder; + float playpos = streamer_get_playpos (); + int minpos = playpos / 60; + int secpos = playpos - minpos * 60; + int mindur = str_playing_song._duration / 60; + int secdur = str_playing_song._duration - mindur * 60; + + const char *mode = c->info.channels == 1 ? "Mono" : "Stereo"; + int samplerate = c->info.samplerate; + int bitspersample = c->info.bps; + songpos = playpos; +// codec_unlock (); + + char t[100]; + if (str_playing_song._duration >= 0) { + snprintf (t, sizeof (t), "%d:%02d", mindur, secdur); + } + else { + strcpy (t, "-:--"); + } + + char sbitrate[20] = ""; +#if 0 // NOTE: do not enable that for stable branch yet + int bitrate = streamer_get_bitrate (); + if (bitrate > 0) { + snprintf (sbitrate, sizeof (sbitrate), "%d kbps ", bitrate); + } +#endif + const char *spaused = p_ispaused () ? "Paused | " : ""; + snprintf (sbtext_new, sizeof (sbtext_new), "%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d songs | %s total playtime", spaused, str_playing_song.filetype ? str_playing_song.filetype:"-", sbitrate, samplerate, bitspersample, mode, minpos, secpos, t, pl_getcount (), totaltime_str); + } + + if (strcmp (sbtext_new, sb_text)) { + strcpy (sb_text, sbtext_new); + + // form statusline + GDK_THREADS_ENTER(); + // FIXME: don't update if window is not visible + GtkStatusbar *sb = GTK_STATUSBAR (lookup_widget (mainwin, "statusbar")); + if (sb_context_id == -1) { + sb_context_id = gtk_statusbar_get_context_id (sb, "msg"); + } + + gtk_statusbar_pop (sb, sb_context_id); + gtk_statusbar_push (sb, sb_context_id, sb_text); + + GDK_THREADS_LEAVE(); + } + + if (songpos != last_songpos) { + void seekbar_draw (GtkWidget *widget); + void seekbar_expose (GtkWidget *widget, int x, int y, int w, int h); + if (mainwin) { + GtkWidget *widget = lookup_widget (mainwin, "seekbar"); + // translate volume to seekbar pixels + songpos /= str_playing_song._duration; + songpos *= widget->allocation.width; + if ((int)(songpos*2) != (int)(last_songpos*2)) { + GDK_THREADS_ENTER(); + seekbar_draw (widget); + seekbar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height); + GDK_THREADS_LEAVE(); + last_songpos = songpos; + } + } + } +} + +gboolean +on_trayicon_scroll_event (GtkWidget *widget, + GdkEventScroll *event, + gpointer user_data) +{ + float vol = volume_get_db (); + if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT) { + vol += 1; + } + else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT) { + vol -= 1; + } + if (vol > 0) { + vol = 0; + } + else if (vol < -60) { + vol = -60; + } + volume_set_db (vol); + GtkWidget *volumebar = lookup_widget (mainwin, "volumebar"); + volumebar_draw (volumebar); + volumebar_expose (volumebar, 0, 0, volumebar->allocation.width, volumebar->allocation.height); + return FALSE; +} + +#if GTK_MINOR_VERSION<=14 +gboolean +on_trayicon_activate (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + if (GTK_WIDGET_VISIBLE (mainwin)) { + gtk_widget_hide (mainwin); + } + else { + gtk_widget_show (mainwin); + gtk_window_present (GTK_WINDOW (mainwin)); + } + return FALSE; +} +#endif + +gboolean +on_trayicon_button_press_event (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + if (event->button == 1) { + if (GTK_WIDGET_VISIBLE (mainwin)) { + gtk_widget_hide (mainwin); + } + else { + gtk_widget_show (mainwin); + gtk_window_present (GTK_WINDOW (mainwin)); + } + } + return FALSE; +} + +gboolean +on_trayicon_popup_menu (GtkWidget *widget, + guint button, + guint time, + gpointer user_data) +{ + gtk_menu_popup (GTK_MENU (traymenu), NULL, NULL, gtk_status_icon_position_menu, trayicon, button, time); + return FALSE; +} + +void +guiplug_showwindow (void) { + GDK_THREADS_ENTER(); + gtk_widget_show (mainwin); + gtk_window_present (GTK_WINDOW (mainwin)); + GDK_THREADS_LEAVE(); +} + +void +guiplug_play_current_song (void) { + GDK_THREADS_ENTER(); + gtkpl_playsong (&main_playlist); + GDK_THREADS_LEAVE(); +} + +void +guiplug_shutdown (void) { + GDK_THREADS_ENTER(); + gtk_widget_hide (mainwin); + gtk_main_quit (); + GDK_THREADS_LEAVE(); +} + +void +guiplug_songchanged (int from, int to) { + gtkpl_songchanged_wrapper (from, to); +} + +void +guiplug_start_current_track (void) { + gtkpl_playsong (&main_playlist); + if (playlist_current_ptr) { + GDK_THREADS_ENTER(); + gtkpl_redraw_pl_row (&main_playlist, pl_get_idx_of (playlist_current_ptr), playlist_current_ptr); + GDK_THREADS_LEAVE(); + } +} +void +guiplug_track_changed (int idx) { + playItem_t *it = pl_get_for_idx (idx); + if (it) { + GDK_THREADS_ENTER(); + gtkpl_redraw_pl_row (&main_playlist, idx, it); + if (it == playlist_current_ptr) { + gtkpl_current_track_changed (it); + } + GDK_THREADS_LEAVE(); + } +} + +void +guiplug_start_track (int idx) { + GDK_THREADS_ENTER(); + gtkpl_playsongnum (idx); + GDK_THREADS_LEAVE(); +} + +void +guiplug_track_paused (int idx) { + GDK_THREADS_ENTER(); + gtkpl_redraw_pl_row (&main_playlist, idx, pl_get_for_idx (idx)); + GDK_THREADS_LEAVE(); +} + +void +guiplug_start_random (void) { + GDK_THREADS_ENTER(); + gtkpl_randomsong (); + GDK_THREADS_LEAVE(); +} + +void +guiplug_add_dir (const char *dir) { + // long time processing + // float t1 = (float)clock () / CLOCKS_PER_SEC; + gtkpl_add_dir (&main_playlist, dir); + // float t2 = (float)clock () / CLOCKS_PER_SEC; + // printf ("time: %f\n", t2-t1); +} + +void +guiplug_add_dirs (GSList *dirs) { + // long time processing + // float t1 = (float)clock () / CLOCKS_PER_SEC; + gtkpl_add_dirs (&main_playlist, dirs); + // float t2 = (float)clock () / CLOCKS_PER_SEC; + // printf ("time: %f\n", t2-t1); +} + +void +guiplug_add_files (GSList *files) { + gtkpl_add_files (&main_playlist, files); +} + +void +guiplug_open_files (GSList *files) { + gtkpl_add_files (&main_playlist, files); + gtkpl_playsong (&main_playlist); +} + +void +guiplug_refresh_playlist (void) { + GDK_THREADS_ENTER(); + playlist_refresh (); + search_refresh (); + GDK_THREADS_LEAVE(); +} + +void +guiplug_add_fm_dropped_files (char *files, int p1, int p2) { + gtkpl_add_fm_dropped_files (&main_playlist, (char *)ctx, p1, p2); +} + +void +guiplug_frameupdate (void) { + update_songinfo (); +} + +void +guiplug_reset_selection (void) { + search_playlist.row = -1; + main_playlist.row = -1; +} + +// define plugin interface +static DB_gui_t plugin = { + DB_PLUGIN_SET_API_VERSION + .plugin.version_major = 0, + .plugin.version_minor = 1, + .plugin.type = DB_PLUGIN_MISC, + .plugin.name = "Standard GTK2 user interface", + .plugin.descr = "", + .plugin.author = "Alexey Yakovenko", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", + .plugin.start = gtkui_start, + .plugin.stop = gtkui_stop +}; diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c new file mode 100644 index 00000000..88acb8d0 --- /dev/null +++ b/plugins/gtkui/interface.c @@ -0,0 +1,1737 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_mainwin (void) +{ + GtkWidget *mainwin; + GtkWidget *vbox1; + GtkWidget *menubar1; + GtkWidget *menuitem1; + GtkWidget *menuitem1_menu; + GtkWidget *open; + GtkWidget *image120; + GtkWidget *separator2; + GtkWidget *add_files; + GtkWidget *image121; + GtkWidget *add_folders; + GtkWidget *image122; + GtkWidget *add_audio_cd; + GtkWidget *image123; + GtkWidget *add_location1; + GtkWidget *separatormenuitem1; + GtkWidget *quit; + GtkWidget *image124; + GtkWidget *edit1; + GtkWidget *edit1_menu; + GtkWidget *clear1; + GtkWidget *image125; + GtkWidget *select_all1; + GtkWidget *selection1; + GtkWidget *selection1_menu; + GtkWidget *remove1; + GtkWidget *image126; + GtkWidget *crop1; + GtkWidget *find1; + GtkWidget *separator5; + GtkWidget *preferences; + GtkWidget *playlist1; + GtkWidget *playlist1_menu; + GtkWidget *playlist_load; + GtkWidget *playlist_save; + GtkWidget *playlist_save_as; + GtkWidget *order1; + GtkWidget *order1_menu; + GSList *order_linear_group = NULL; + GtkWidget *order_linear; + GtkWidget *order_shuffle; + GtkWidget *order_random; + GtkWidget *looping1; + GtkWidget *looping1_menu; + GSList *loop_all_group = NULL; + GtkWidget *loop_all; + GtkWidget *loop_single; + GtkWidget *loop_disable; + GtkWidget *scroll_follows_playback; + GtkWidget *menuitem4; + GtkWidget *menuitem4_menu; + GtkWidget *about1; + GtkWidget *help1; + GtkWidget *image127; + GtkWidget *hbox2; + GtkWidget *hbox3; + GtkWidget *stopbtn; + GtkWidget *image7; + GtkWidget *playbtn; + GtkWidget *image2; + GtkWidget *pausebtn; + GtkWidget *image3; + GtkWidget *prevbtn; + GtkWidget *image4; + GtkWidget *nextbtn; + GtkWidget *image5; + GtkWidget *playrand; + GtkWidget *image6; + GtkWidget *volumebar; + GtkWidget *seekbar; + GtkWidget *table1; + GtkWidget *_; + GtkWidget *vbox3; + GtkWidget *header; + GtkWidget *playlist; + GtkWidget *playscroll; + GtkWidget *playhscroll; + GtkWidget *statusbar; + GtkAccelGroup *accel_group; + + accel_group = gtk_accel_group_new (); + + mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_events (mainwin, GDK_KEY_PRESS_MASK); + gtk_window_set_title (GTK_WINDOW (mainwin), "DeaDBeeF"); + gtk_window_set_default_size (GTK_WINDOW (mainwin), 500, 300); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (mainwin), vbox1); + + menubar1 = gtk_menu_bar_new (); + gtk_widget_show (menubar1); + gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0); + + menuitem1 = gtk_menu_item_new_with_mnemonic ("_File"); + gtk_widget_show (menuitem1); + gtk_container_add (GTK_CONTAINER (menubar1), menuitem1); + + menuitem1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menuitem1_menu); + + open = gtk_image_menu_item_new_with_mnemonic ("_Open file(s)"); + gtk_widget_show (open); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), open); + gtk_widget_add_accelerator (open, "activate", accel_group, + GDK_O, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); + + image120 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_MENU); + gtk_widget_show (image120); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (open), image120); + + separator2 = gtk_separator_menu_item_new (); + gtk_widget_show (separator2); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), separator2); + gtk_widget_set_sensitive (separator2, FALSE); + + add_files = gtk_image_menu_item_new_with_mnemonic ("Add file(s)"); + gtk_widget_show (add_files); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_files); + + image121 = gtk_image_new_from_stock ("gtk-add", GTK_ICON_SIZE_MENU); + gtk_widget_show (image121); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_files), image121); + + add_folders = gtk_image_menu_item_new_with_mnemonic ("Add folder(s)"); + gtk_widget_show (add_folders); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_folders); + + image122 = gtk_image_new_from_stock ("gtk-add", GTK_ICON_SIZE_MENU); + gtk_widget_show (image122); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_folders), image122); + + add_audio_cd = gtk_image_menu_item_new_with_mnemonic ("Add Audio CD"); + gtk_widget_show (add_audio_cd); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_audio_cd); + + image123 = gtk_image_new_from_stock ("gtk-add", GTK_ICON_SIZE_MENU); + gtk_widget_show (image123); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_audio_cd), image123); + + add_location1 = gtk_menu_item_new_with_mnemonic ("Add location"); + gtk_widget_show (add_location1); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_location1); + + separatormenuitem1 = gtk_separator_menu_item_new (); + gtk_widget_show (separatormenuitem1); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), separatormenuitem1); + gtk_widget_set_sensitive (separatormenuitem1, FALSE); + + quit = gtk_image_menu_item_new_with_mnemonic ("_Quit"); + gtk_widget_show (quit); + gtk_container_add (GTK_CONTAINER (menuitem1_menu), quit); + gtk_widget_add_accelerator (quit, "activate", accel_group, + GDK_Q, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); + + image124 = gtk_image_new_from_stock ("gtk-quit", GTK_ICON_SIZE_MENU); + gtk_widget_show (image124); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (quit), image124); + + edit1 = gtk_menu_item_new_with_mnemonic ("Edit"); + gtk_widget_show (edit1); + gtk_container_add (GTK_CONTAINER (menubar1), edit1); + + edit1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (edit1), edit1_menu); + + clear1 = gtk_image_menu_item_new_with_mnemonic ("_Clear"); + gtk_widget_show (clear1); + gtk_container_add (GTK_CONTAINER (edit1_menu), clear1); + + image125 = gtk_image_new_from_stock ("gtk-clear", GTK_ICON_SIZE_MENU); + gtk_widget_show (image125); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (clear1), image125); + + select_all1 = gtk_menu_item_new_with_mnemonic ("Select all"); + gtk_widget_show (select_all1); + gtk_container_add (GTK_CONTAINER (edit1_menu), select_all1); + gtk_widget_add_accelerator (select_all1, "activate", accel_group, + GDK_A, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); + + selection1 = gtk_menu_item_new_with_mnemonic ("Selection"); + gtk_widget_show (selection1); + gtk_container_add (GTK_CONTAINER (edit1_menu), selection1); + + selection1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (selection1), selection1_menu); + + remove1 = gtk_image_menu_item_new_with_mnemonic ("Remove"); + gtk_widget_show (remove1); + gtk_container_add (GTK_CONTAINER (selection1_menu), remove1); + gtk_widget_add_accelerator (remove1, "activate", accel_group, + GDK_Delete, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + + image126 = gtk_image_new_from_stock ("gtk-remove", GTK_ICON_SIZE_MENU); + gtk_widget_show (image126); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (remove1), image126); + + crop1 = gtk_menu_item_new_with_mnemonic ("Crop"); + gtk_widget_show (crop1); + gtk_container_add (GTK_CONTAINER (selection1_menu), crop1); + + find1 = gtk_menu_item_new_with_mnemonic ("_Find"); + gtk_widget_show (find1); + gtk_container_add (GTK_CONTAINER (edit1_menu), find1); + gtk_widget_add_accelerator (find1, "activate", accel_group, + GDK_F, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); + + separator5 = gtk_separator_menu_item_new (); + gtk_widget_show (separator5); + gtk_container_add (GTK_CONTAINER (edit1_menu), separator5); + gtk_widget_set_sensitive (separator5, FALSE); + + preferences = gtk_menu_item_new_with_mnemonic ("Preferences"); + gtk_widget_show (preferences); + gtk_container_add (GTK_CONTAINER (edit1_menu), preferences); + + playlist1 = gtk_menu_item_new_with_mnemonic ("Playlist"); + gtk_widget_show (playlist1); + gtk_container_add (GTK_CONTAINER (menubar1), playlist1); + + playlist1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (playlist1), playlist1_menu); + + playlist_load = gtk_menu_item_new_with_mnemonic ("Load"); + gtk_widget_show (playlist_load); + gtk_container_add (GTK_CONTAINER (playlist1_menu), playlist_load); + + playlist_save = gtk_menu_item_new_with_mnemonic ("Save"); + gtk_widget_show (playlist_save); + gtk_container_add (GTK_CONTAINER (playlist1_menu), playlist_save); + + playlist_save_as = gtk_menu_item_new_with_mnemonic ("Save As"); + gtk_widget_show (playlist_save_as); + gtk_container_add (GTK_CONTAINER (playlist1_menu), playlist_save_as); + + order1 = gtk_menu_item_new_with_mnemonic ("Order"); + gtk_widget_show (order1); + gtk_container_add (GTK_CONTAINER (playlist1_menu), order1); + + order1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (order1), order1_menu); + + order_linear = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Linear"); + order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_linear)); + gtk_widget_show (order_linear); + gtk_container_add (GTK_CONTAINER (order1_menu), order_linear); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_linear), TRUE); + + order_shuffle = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Shuffle"); + order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_shuffle)); + gtk_widget_show (order_shuffle); + gtk_container_add (GTK_CONTAINER (order1_menu), order_shuffle); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_shuffle), TRUE); + + order_random = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Random"); + order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_random)); + gtk_widget_show (order_random); + gtk_container_add (GTK_CONTAINER (order1_menu), order_random); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_random), TRUE); + + looping1 = gtk_menu_item_new_with_mnemonic ("Looping"); + gtk_widget_show (looping1); + gtk_container_add (GTK_CONTAINER (playlist1_menu), looping1); + + looping1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (looping1), looping1_menu); + + loop_all = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Loop All"); + loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_all)); + gtk_widget_show (loop_all); + gtk_container_add (GTK_CONTAINER (looping1_menu), loop_all); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_all), TRUE); + + loop_single = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Loop Single Song"); + loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_single)); + gtk_widget_show (loop_single); + gtk_container_add (GTK_CONTAINER (looping1_menu), loop_single); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_single), TRUE); + + loop_disable = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Don't Loop"); + loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_disable)); + gtk_widget_show (loop_disable); + gtk_container_add (GTK_CONTAINER (looping1_menu), loop_disable); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_disable), TRUE); + + scroll_follows_playback = gtk_check_menu_item_new_with_mnemonic ("Scroll follows playback"); + gtk_widget_show (scroll_follows_playback); + gtk_container_add (GTK_CONTAINER (playlist1_menu), scroll_follows_playback); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (scroll_follows_playback), TRUE); + + menuitem4 = gtk_menu_item_new_with_mnemonic ("_Help"); + gtk_widget_show (menuitem4); + gtk_container_add (GTK_CONTAINER (menubar1), menuitem4); + + menuitem4_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem4), menuitem4_menu); + + about1 = gtk_menu_item_new_with_mnemonic ("_About"); + gtk_widget_show (about1); + gtk_container_add (GTK_CONTAINER (menuitem4_menu), about1); + + help1 = gtk_image_menu_item_new_with_mnemonic ("Help"); + gtk_widget_show (help1); + gtk_container_add (GTK_CONTAINER (menuitem4_menu), help1); + + image127 = gtk_image_new_from_stock ("gtk-help", GTK_ICON_SIZE_MENU); + gtk_widget_show (image127); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (help1), image127); + + hbox2 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox1), hbox2, FALSE, FALSE, 0); + + hbox3 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox3); + gtk_box_pack_start (GTK_BOX (hbox2), hbox3, TRUE, TRUE, 0); + + stopbtn = gtk_button_new (); + gtk_widget_show (stopbtn); + gtk_box_pack_start (GTK_BOX (hbox3), stopbtn, FALSE, FALSE, 0); + GTK_WIDGET_UNSET_FLAGS (stopbtn, GTK_CAN_FOCUS); + gtk_widget_add_accelerator (stopbtn, "activate", accel_group, + GDK_v, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + gtk_button_set_relief (GTK_BUTTON (stopbtn), GTK_RELIEF_NONE); + + image7 = create_pixmap (mainwin, "stop_24.png"); + gtk_widget_show (image7); + gtk_container_add (GTK_CONTAINER (stopbtn), image7); + + playbtn = gtk_button_new (); + gtk_widget_show (playbtn); + gtk_box_pack_start (GTK_BOX (hbox3), playbtn, FALSE, FALSE, 0); + GTK_WIDGET_UNSET_FLAGS (playbtn, GTK_CAN_FOCUS); + gtk_widget_add_accelerator (playbtn, "activate", accel_group, + GDK_x, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + gtk_widget_add_accelerator (playbtn, "activate", accel_group, + GDK_Return, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + gtk_button_set_relief (GTK_BUTTON (playbtn), GTK_RELIEF_NONE); + + image2 = create_pixmap (mainwin, "play_24.png"); + gtk_widget_show (image2); + gtk_container_add (GTK_CONTAINER (playbtn), image2); + + pausebtn = gtk_button_new (); + gtk_widget_show (pausebtn); + gtk_box_pack_start (GTK_BOX (hbox3), pausebtn, FALSE, FALSE, 0); + GTK_WIDGET_UNSET_FLAGS (pausebtn, GTK_CAN_FOCUS); + gtk_widget_add_accelerator (pausebtn, "activate", accel_group, + GDK_c, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + gtk_widget_add_accelerator (pausebtn, "activate", accel_group, + GDK_p, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); + gtk_button_set_relief (GTK_BUTTON (pausebtn), GTK_RELIEF_NONE); + + image3 = create_pixmap (mainwin, "pause_24.png"); + gtk_widget_show (image3); + gtk_container_add (GTK_CONTAINER (pausebtn), image3); + + prevbtn = gtk_button_new (); + gtk_widget_show (prevbtn); + gtk_box_pack_start (GTK_BOX (hbox3), prevbtn, FALSE, FALSE, 0); + GTK_WIDGET_UNSET_FLAGS (prevbtn, GTK_CAN_FOCUS); + gtk_widget_add_accelerator (prevbtn, "activate", accel_group, + GDK_z, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + gtk_button_set_relief (GTK_BUTTON (prevbtn), GTK_RELIEF_NONE); + + image4 = create_pixmap (mainwin, "prev_24.png"); + gtk_widget_show (image4); + gtk_container_add (GTK_CONTAINER (prevbtn), image4); + + nextbtn = gtk_button_new (); + gtk_widget_show (nextbtn); + gtk_box_pack_start (GTK_BOX (hbox3), nextbtn, FALSE, FALSE, 0); + GTK_WIDGET_UNSET_FLAGS (nextbtn, GTK_CAN_FOCUS); + gtk_widget_add_accelerator (nextbtn, "activate", accel_group, + GDK_b, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + gtk_button_set_relief (GTK_BUTTON (nextbtn), GTK_RELIEF_NONE); + + image5 = create_pixmap (mainwin, "next_24.png"); + gtk_widget_show (image5); + gtk_container_add (GTK_CONTAINER (nextbtn), image5); + + playrand = gtk_button_new (); + gtk_widget_show (playrand); + gtk_box_pack_start (GTK_BOX (hbox3), playrand, FALSE, FALSE, 0); + GTK_WIDGET_UNSET_FLAGS (playrand, GTK_CAN_FOCUS); + gtk_widget_add_accelerator (playrand, "activate", accel_group, + GDK_n, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); + gtk_button_set_relief (GTK_BUTTON (playrand), GTK_RELIEF_NONE); + + image6 = create_pixmap (mainwin, "random_24.png"); + gtk_widget_show (image6); + gtk_container_add (GTK_CONTAINER (playrand), image6); + + volumebar = gtk_drawing_area_new (); + gtk_widget_show (volumebar); + gtk_box_pack_start (GTK_BOX (hbox2), volumebar, FALSE, TRUE, 2); + gtk_widget_set_size_request (volumebar, 70, -1); + gtk_widget_set_events (volumebar, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + + seekbar = gtk_drawing_area_new (); + gtk_widget_show (seekbar); + gtk_box_pack_start (GTK_BOX (hbox2), seekbar, FALSE, TRUE, 2); + gtk_widget_set_size_request (seekbar, 200, -1); + gtk_widget_set_events (seekbar, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + + table1 = gtk_table_new (2, 2, FALSE); + gtk_widget_show (table1); + gtk_box_pack_start (GTK_BOX (vbox1), table1, TRUE, TRUE, 0); + + _ = gtk_hbox_new (FALSE, 0); + gtk_widget_show (_); + gtk_table_attach (GTK_TABLE (table1), _, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_container_set_border_width (GTK_CONTAINER (_), 3); + + vbox3 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox3); + gtk_box_pack_start (GTK_BOX (_), vbox3, TRUE, TRUE, 0); + + header = gtk_drawing_area_new (); + gtk_widget_show (header); + gtk_box_pack_start (GTK_BOX (vbox3), header, FALSE, TRUE, 0); + gtk_widget_set_size_request (header, -1, 24); + gtk_widget_set_events (header, GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + + playlist = gtk_drawing_area_new (); + gtk_widget_show (playlist); + gtk_box_pack_start (GTK_BOX (vbox3), playlist, TRUE, TRUE, 0); + gtk_widget_set_events (playlist, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); + + playscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 1, 1, 0, 0))); + gtk_widget_show (playscroll); + gtk_table_attach (GTK_TABLE (table1), playscroll, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + playhscroll = gtk_hscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 0, 0, 0, 0))); + gtk_widget_show (playhscroll); + gtk_table_attach (GTK_TABLE (table1), playhscroll, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + statusbar = gtk_statusbar_new (); + gtk_widget_show (statusbar); + gtk_box_pack_start (GTK_BOX (vbox1), statusbar, FALSE, FALSE, 0); + + g_signal_connect ((gpointer) mainwin, "key_press_event", + G_CALLBACK (on_mainwin_key_press_event), + NULL); + g_signal_connect ((gpointer) mainwin, "delete_event", + G_CALLBACK (on_mainwin_delete_event), + NULL); + g_signal_connect ((gpointer) mainwin, "configure_event", + G_CALLBACK (on_mainwin_configure_event), + NULL); + g_signal_connect ((gpointer) open, "activate", + G_CALLBACK (on_open_activate), + NULL); + g_signal_connect ((gpointer) add_files, "activate", + G_CALLBACK (on_add_files_activate), + NULL); + g_signal_connect ((gpointer) add_folders, "activate", + G_CALLBACK (on_add_folders_activate), + NULL); + g_signal_connect ((gpointer) add_audio_cd, "activate", + G_CALLBACK (on_add_audio_cd_activate), + NULL); + g_signal_connect ((gpointer) add_location1, "activate", + G_CALLBACK (on_add_location_activate), + NULL); + g_signal_connect ((gpointer) quit, "activate", + G_CALLBACK (on_quit_activate), + NULL); + g_signal_connect ((gpointer) clear1, "activate", + G_CALLBACK (on_clear1_activate), + NULL); + g_signal_connect ((gpointer) select_all1, "activate", + G_CALLBACK (on_select_all1_activate), + NULL); + g_signal_connect ((gpointer) remove1, "activate", + G_CALLBACK (on_remove1_activate), + NULL); + g_signal_connect ((gpointer) crop1, "activate", + G_CALLBACK (on_crop1_activate), + NULL); + g_signal_connect ((gpointer) find1, "activate", + G_CALLBACK (on_find_activate), + NULL); + g_signal_connect ((gpointer) preferences, "activate", + G_CALLBACK (on_preferences_activate), + NULL); + g_signal_connect ((gpointer) playlist_load, "activate", + G_CALLBACK (on_playlist_load_activate), + NULL); + g_signal_connect ((gpointer) playlist_save, "activate", + G_CALLBACK (on_playlist_save_activate), + NULL); + g_signal_connect ((gpointer) playlist_save_as, "activate", + G_CALLBACK (on_playlist_save_as_activate), + NULL); + g_signal_connect ((gpointer) order_linear, "activate", + G_CALLBACK (on_order_linear_activate), + NULL); + g_signal_connect ((gpointer) order_shuffle, "activate", + G_CALLBACK (on_order_shuffle_activate), + NULL); + g_signal_connect ((gpointer) order_random, "activate", + G_CALLBACK (on_order_random_activate), + NULL); + g_signal_connect ((gpointer) loop_all, "activate", + G_CALLBACK (on_loop_all_activate), + NULL); + g_signal_connect ((gpointer) loop_single, "activate", + G_CALLBACK (on_loop_single_activate), + NULL); + g_signal_connect ((gpointer) loop_disable, "activate", + G_CALLBACK (on_loop_disable_activate), + NULL); + g_signal_connect ((gpointer) scroll_follows_playback, "activate", + G_CALLBACK (on_scroll_follows_playback_activate), + NULL); + g_signal_connect ((gpointer) about1, "activate", + G_CALLBACK (on_about1_activate), + NULL); + g_signal_connect ((gpointer) help1, "activate", + G_CALLBACK (on_help1_activate), + NULL); + g_signal_connect ((gpointer) stopbtn, "clicked", + G_CALLBACK (on_stopbtn_clicked), + NULL); + g_signal_connect ((gpointer) playbtn, "clicked", + G_CALLBACK (on_playbtn_clicked), + NULL); + g_signal_connect ((gpointer) pausebtn, "clicked", + G_CALLBACK (on_pausebtn_clicked), + NULL); + g_signal_connect ((gpointer) prevbtn, "clicked", + G_CALLBACK (on_prevbtn_clicked), + NULL); + g_signal_connect ((gpointer) nextbtn, "clicked", + G_CALLBACK (on_nextbtn_clicked), + NULL); + g_signal_connect ((gpointer) playrand, "clicked", + G_CALLBACK (on_playrand_clicked), + NULL); + g_signal_connect ((gpointer) volumebar, "button_press_event", + G_CALLBACK (on_volumebar_button_press_event), + NULL); + g_signal_connect ((gpointer) volumebar, "button_release_event", + G_CALLBACK (on_volumebar_button_release_event), + NULL); + g_signal_connect ((gpointer) volumebar, "configure_event", + G_CALLBACK (on_volumebar_configure_event), + NULL); + g_signal_connect ((gpointer) volumebar, "expose_event", + G_CALLBACK (on_volumebar_expose_event), + NULL); + g_signal_connect ((gpointer) volumebar, "motion_notify_event", + G_CALLBACK (on_volumebar_motion_notify_event), + NULL); + g_signal_connect ((gpointer) volumebar, "scroll_event", + G_CALLBACK (on_volumebar_scroll_event), + NULL); + g_signal_connect ((gpointer) seekbar, "button_press_event", + G_CALLBACK (on_seekbar_button_press_event), + NULL); + g_signal_connect ((gpointer) seekbar, "button_release_event", + G_CALLBACK (on_seekbar_button_release_event), + NULL); + g_signal_connect ((gpointer) seekbar, "configure_event", + G_CALLBACK (on_seekbar_configure_event), + NULL); + g_signal_connect ((gpointer) seekbar, "expose_event", + G_CALLBACK (on_seekbar_expose_event), + NULL); + g_signal_connect ((gpointer) seekbar, "motion_notify_event", + G_CALLBACK (on_seekbar_motion_notify_event), + NULL); + g_signal_connect ((gpointer) header, "expose_event", + G_CALLBACK (on_header_expose_event), + NULL); + g_signal_connect ((gpointer) header, "configure_event", + G_CALLBACK (on_header_configure_event), + NULL); + g_signal_connect ((gpointer) header, "realize", + G_CALLBACK (on_header_realize), + NULL); + g_signal_connect ((gpointer) header, "motion_notify_event", + G_CALLBACK (on_header_motion_notify_event), + NULL); + g_signal_connect ((gpointer) header, "button_press_event", + G_CALLBACK (on_header_button_press_event), + NULL); + g_signal_connect ((gpointer) header, "button_release_event", + G_CALLBACK (on_header_button_release_event), + NULL); + g_signal_connect ((gpointer) playlist, "configure_event", + G_CALLBACK (on_playlist_configure_event), + NULL); + g_signal_connect ((gpointer) playlist, "expose_event", + G_CALLBACK (on_playlist_expose_event), + NULL); + g_signal_connect ((gpointer) playlist, "realize", + G_CALLBACK (on_playlist_realize), + NULL); + g_signal_connect ((gpointer) playlist, "button_press_event", + G_CALLBACK (on_playlist_button_press_event), + NULL); + g_signal_connect ((gpointer) playlist, "scroll_event", + G_CALLBACK (on_playlist_scroll_event), + NULL); + g_signal_connect ((gpointer) playlist, "drag_begin", + G_CALLBACK (on_playlist_drag_begin), + NULL); + g_signal_connect ((gpointer) playlist, "drag_motion", + G_CALLBACK (on_playlist_drag_motion), + NULL); + g_signal_connect ((gpointer) playlist, "drag_drop", + G_CALLBACK (on_playlist_drag_drop), + NULL); + g_signal_connect ((gpointer) playlist, "drag_data_get", + G_CALLBACK (on_playlist_drag_data_get), + NULL); + g_signal_connect ((gpointer) playlist, "drag_end", + G_CALLBACK (on_playlist_drag_end), + NULL); + g_signal_connect ((gpointer) playlist, "drag_failed", + G_CALLBACK (on_playlist_drag_failed), + NULL); + g_signal_connect ((gpointer) playlist, "drag_leave", + G_CALLBACK (on_playlist_drag_leave), + NULL); + g_signal_connect ((gpointer) playlist, "button_release_event", + G_CALLBACK (on_playlist_button_release_event), + NULL); + g_signal_connect ((gpointer) playlist, "motion_notify_event", + G_CALLBACK (on_playlist_motion_notify_event), + NULL); + g_signal_connect ((gpointer) playlist, "drag_data_received", + G_CALLBACK (on_playlist_drag_data_received), + NULL); + g_signal_connect ((gpointer) playlist, "drag_data_delete", + G_CALLBACK (on_playlist_drag_data_delete), + NULL); + g_signal_connect ((gpointer) playscroll, "value_changed", + G_CALLBACK (on_playscroll_value_changed), + NULL); + g_signal_connect ((gpointer) playhscroll, "value_changed", + G_CALLBACK (on_playhscroll_value_changed), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (mainwin, mainwin, "mainwin"); + GLADE_HOOKUP_OBJECT (mainwin, vbox1, "vbox1"); + GLADE_HOOKUP_OBJECT (mainwin, menubar1, "menubar1"); + GLADE_HOOKUP_OBJECT (mainwin, menuitem1, "menuitem1"); + GLADE_HOOKUP_OBJECT (mainwin, menuitem1_menu, "menuitem1_menu"); + GLADE_HOOKUP_OBJECT (mainwin, open, "open"); + GLADE_HOOKUP_OBJECT (mainwin, image120, "image120"); + GLADE_HOOKUP_OBJECT (mainwin, separator2, "separator2"); + GLADE_HOOKUP_OBJECT (mainwin, add_files, "add_files"); + GLADE_HOOKUP_OBJECT (mainwin, image121, "image121"); + GLADE_HOOKUP_OBJECT (mainwin, add_folders, "add_folders"); + GLADE_HOOKUP_OBJECT (mainwin, image122, "image122"); + GLADE_HOOKUP_OBJECT (mainwin, add_audio_cd, "add_audio_cd"); + GLADE_HOOKUP_OBJECT (mainwin, image123, "image123"); + GLADE_HOOKUP_OBJECT (mainwin, add_location1, "add_location1"); + GLADE_HOOKUP_OBJECT (mainwin, separatormenuitem1, "separatormenuitem1"); + GLADE_HOOKUP_OBJECT (mainwin, quit, "quit"); + GLADE_HOOKUP_OBJECT (mainwin, image124, "image124"); + GLADE_HOOKUP_OBJECT (mainwin, edit1, "edit1"); + GLADE_HOOKUP_OBJECT (mainwin, edit1_menu, "edit1_menu"); + GLADE_HOOKUP_OBJECT (mainwin, clear1, "clear1"); + GLADE_HOOKUP_OBJECT (mainwin, image125, "image125"); + GLADE_HOOKUP_OBJECT (mainwin, select_all1, "select_all1"); + GLADE_HOOKUP_OBJECT (mainwin, selection1, "selection1"); + GLADE_HOOKUP_OBJECT (mainwin, selection1_menu, "selection1_menu"); + GLADE_HOOKUP_OBJECT (mainwin, remove1, "remove1"); + GLADE_HOOKUP_OBJECT (mainwin, image126, "image126"); + GLADE_HOOKUP_OBJECT (mainwin, crop1, "crop1"); + GLADE_HOOKUP_OBJECT (mainwin, find1, "find1"); + GLADE_HOOKUP_OBJECT (mainwin, separator5, "separator5"); + GLADE_HOOKUP_OBJECT (mainwin, preferences, "preferences"); + GLADE_HOOKUP_OBJECT (mainwin, playlist1, "playlist1"); + GLADE_HOOKUP_OBJECT (mainwin, playlist1_menu, "playlist1_menu"); + GLADE_HOOKUP_OBJECT (mainwin, playlist_load, "playlist_load"); + GLADE_HOOKUP_OBJECT (mainwin, playlist_save, "playlist_save"); + GLADE_HOOKUP_OBJECT (mainwin, playlist_save_as, "playlist_save_as"); + GLADE_HOOKUP_OBJECT (mainwin, order1, "order1"); + GLADE_HOOKUP_OBJECT (mainwin, order1_menu, "order1_menu"); + GLADE_HOOKUP_OBJECT (mainwin, order_linear, "order_linear"); + GLADE_HOOKUP_OBJECT (mainwin, order_shuffle, "order_shuffle"); + GLADE_HOOKUP_OBJECT (mainwin, order_random, "order_random"); + GLADE_HOOKUP_OBJECT (mainwin, looping1, "looping1"); + GLADE_HOOKUP_OBJECT (mainwin, looping1_menu, "looping1_menu"); + GLADE_HOOKUP_OBJECT (mainwin, loop_all, "loop_all"); + GLADE_HOOKUP_OBJECT (mainwin, loop_single, "loop_single"); + GLADE_HOOKUP_OBJECT (mainwin, loop_disable, "loop_disable"); + GLADE_HOOKUP_OBJECT (mainwin, scroll_follows_playback, "scroll_follows_playback"); + GLADE_HOOKUP_OBJECT (mainwin, menuitem4, "menuitem4"); + GLADE_HOOKUP_OBJECT (mainwin, menuitem4_menu, "menuitem4_menu"); + GLADE_HOOKUP_OBJECT (mainwin, about1, "about1"); + GLADE_HOOKUP_OBJECT (mainwin, help1, "help1"); + GLADE_HOOKUP_OBJECT (mainwin, image127, "image127"); + GLADE_HOOKUP_OBJECT (mainwin, hbox2, "hbox2"); + GLADE_HOOKUP_OBJECT (mainwin, hbox3, "hbox3"); + GLADE_HOOKUP_OBJECT (mainwin, stopbtn, "stopbtn"); + GLADE_HOOKUP_OBJECT (mainwin, image7, "image7"); + GLADE_HOOKUP_OBJECT (mainwin, playbtn, "playbtn"); + GLADE_HOOKUP_OBJECT (mainwin, image2, "image2"); + GLADE_HOOKUP_OBJECT (mainwin, pausebtn, "pausebtn"); + GLADE_HOOKUP_OBJECT (mainwin, image3, "image3"); + GLADE_HOOKUP_OBJECT (mainwin, prevbtn, "prevbtn"); + GLADE_HOOKUP_OBJECT (mainwin, image4, "image4"); + GLADE_HOOKUP_OBJECT (mainwin, nextbtn, "nextbtn"); + GLADE_HOOKUP_OBJECT (mainwin, image5, "image5"); + GLADE_HOOKUP_OBJECT (mainwin, playrand, "playrand"); + GLADE_HOOKUP_OBJECT (mainwin, image6, "image6"); + GLADE_HOOKUP_OBJECT (mainwin, volumebar, "volumebar"); + GLADE_HOOKUP_OBJECT (mainwin, seekbar, "seekbar"); + GLADE_HOOKUP_OBJECT (mainwin, table1, "table1"); + GLADE_HOOKUP_OBJECT (mainwin, _, "_"); + GLADE_HOOKUP_OBJECT (mainwin, vbox3, "vbox3"); + GLADE_HOOKUP_OBJECT (mainwin, header, "header"); + GLADE_HOOKUP_OBJECT (mainwin, playlist, "playlist"); + GLADE_HOOKUP_OBJECT (mainwin, playscroll, "playscroll"); + GLADE_HOOKUP_OBJECT (mainwin, playhscroll, "playhscroll"); + GLADE_HOOKUP_OBJECT (mainwin, statusbar, "statusbar"); + + gtk_window_add_accel_group (GTK_WINDOW (mainwin), accel_group); + + return mainwin; +} + +GtkWidget* +create_searchwin (void) +{ + GtkWidget *searchwin; + GtkWidget *vbox4; + GtkWidget *searchentry; + GtkWidget *table2; + GtkWidget *searchscroll; + GtkWidget *vbox5; + GtkWidget *searchheader; + GtkWidget *searchlist; + GtkWidget *searchhscroll; + + searchwin = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_size_request (searchwin, 600, 150); + gtk_widget_set_events (searchwin, GDK_KEY_PRESS_MASK); + gtk_window_set_title (GTK_WINDOW (searchwin), "Search"); + gtk_window_set_position (GTK_WINDOW (searchwin), GTK_WIN_POS_CENTER_ALWAYS); + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (searchwin), TRUE); + gtk_window_set_skip_pager_hint (GTK_WINDOW (searchwin), TRUE); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox4); + gtk_container_add (GTK_CONTAINER (searchwin), vbox4); + gtk_container_set_border_width (GTK_CONTAINER (vbox4), 4); + + searchentry = gtk_entry_new (); + gtk_widget_show (searchentry); + gtk_box_pack_start (GTK_BOX (vbox4), searchentry, FALSE, FALSE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (searchentry), 8226); + gtk_entry_set_activates_default (GTK_ENTRY (searchentry), TRUE); + + table2 = gtk_table_new (2, 2, FALSE); + gtk_widget_show (table2); + gtk_box_pack_start (GTK_BOX (vbox4), table2, TRUE, TRUE, 0); + + searchscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 1, 1, 0, 0))); + gtk_widget_show (searchscroll); + gtk_table_attach (GTK_TABLE (table2), searchscroll, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox5); + gtk_table_attach (GTK_TABLE (table2), vbox5, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + + searchheader = gtk_drawing_area_new (); + gtk_widget_show (searchheader); + gtk_box_pack_start (GTK_BOX (vbox5), searchheader, FALSE, TRUE, 0); + gtk_widget_set_size_request (searchheader, -1, 24); + gtk_widget_set_events (searchheader, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + + searchlist = gtk_drawing_area_new (); + gtk_widget_show (searchlist); + gtk_box_pack_start (GTK_BOX (vbox5), searchlist, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (searchlist, GTK_CAN_DEFAULT); + gtk_widget_set_events (searchlist, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); + + searchhscroll = gtk_hscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 0, 0, 0, 0))); + gtk_widget_show (searchhscroll); + gtk_table_attach (GTK_TABLE (table2), searchhscroll, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + g_signal_connect ((gpointer) searchwin, "key_press_event", + G_CALLBACK (on_searchwin_key_press_event), + NULL); + g_signal_connect ((gpointer) searchwin, "delete_event", + G_CALLBACK (gtk_widget_hide_on_delete), + NULL); + g_signal_connect ((gpointer) searchentry, "changed", + G_CALLBACK (on_searchentry_changed), + NULL); + g_signal_connect ((gpointer) searchscroll, "value_changed", + G_CALLBACK (on_playscroll_value_changed), + NULL); + g_signal_connect ((gpointer) searchheader, "button_press_event", + G_CALLBACK (on_header_button_press_event), + NULL); + g_signal_connect ((gpointer) searchheader, "button_release_event", + G_CALLBACK (on_header_button_release_event), + NULL); + g_signal_connect ((gpointer) searchheader, "configure_event", + G_CALLBACK (on_header_configure_event), + NULL); + g_signal_connect ((gpointer) searchheader, "expose_event", + G_CALLBACK (on_header_expose_event), + NULL); + g_signal_connect ((gpointer) searchheader, "motion_notify_event", + G_CALLBACK (on_header_motion_notify_event), + NULL); + g_signal_connect ((gpointer) searchlist, "button_press_event", + G_CALLBACK (on_playlist_button_press_event), + NULL); + g_signal_connect ((gpointer) searchlist, "configure_event", + G_CALLBACK (on_searchlist_configure_event), + NULL); + g_signal_connect ((gpointer) searchlist, "expose_event", + G_CALLBACK (on_playlist_expose_event), + NULL); + g_signal_connect ((gpointer) searchlist, "scroll_event", + G_CALLBACK (on_playlist_scroll_event), + NULL); + g_signal_connect ((gpointer) searchlist, "realize", + G_CALLBACK (on_searchlist_realize), + NULL); + g_signal_connect ((gpointer) searchlist, "button_release_event", + G_CALLBACK (on_playlist_button_release_event), + NULL); + g_signal_connect ((gpointer) searchlist, "motion_notify_event", + G_CALLBACK (on_playlist_motion_notify_event), + NULL); + g_signal_connect ((gpointer) searchhscroll, "value_changed", + G_CALLBACK (on_searchhscroll_value_changed), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (searchwin, searchwin, "searchwin"); + GLADE_HOOKUP_OBJECT (searchwin, vbox4, "vbox4"); + GLADE_HOOKUP_OBJECT (searchwin, searchentry, "searchentry"); + GLADE_HOOKUP_OBJECT (searchwin, table2, "table2"); + GLADE_HOOKUP_OBJECT (searchwin, searchscroll, "searchscroll"); + GLADE_HOOKUP_OBJECT (searchwin, vbox5, "vbox5"); + GLADE_HOOKUP_OBJECT (searchwin, searchheader, "searchheader"); + GLADE_HOOKUP_OBJECT (searchwin, searchlist, "searchlist"); + GLADE_HOOKUP_OBJECT (searchwin, searchhscroll, "searchhscroll"); + + gtk_widget_grab_default (searchlist); + return searchwin; +} + +GtkWidget* +create_traymenu (void) +{ + GtkWidget *traymenu; + GtkWidget *stop2; + GtkWidget *image59; + GtkWidget *play2; + GtkWidget *image60; + GtkWidget *pause2; + GtkWidget *image61; + GtkWidget *previous2; + GtkWidget *image62; + GtkWidget *next2; + GtkWidget *image63; + GtkWidget *play_random1; + GtkWidget *separator4; + GtkWidget *about3; + GtkWidget *image64; + GtkWidget *separator3; + GtkWidget *quit; + GtkWidget *image65; + + traymenu = gtk_menu_new (); + + stop2 = gtk_image_menu_item_new_with_mnemonic ("Stop"); + gtk_widget_show (stop2); + gtk_container_add (GTK_CONTAINER (traymenu), stop2); + + image59 = gtk_image_new_from_stock ("gtk-media-stop", GTK_ICON_SIZE_MENU); + gtk_widget_show (image59); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (stop2), image59); + + play2 = gtk_image_menu_item_new_with_mnemonic ("Play"); + gtk_widget_show (play2); + gtk_container_add (GTK_CONTAINER (traymenu), play2); + + image60 = gtk_image_new_from_stock ("gtk-media-play", GTK_ICON_SIZE_MENU); + gtk_widget_show (image60); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (play2), image60); + + pause2 = gtk_image_menu_item_new_with_mnemonic ("Pause"); + gtk_widget_show (pause2); + gtk_container_add (GTK_CONTAINER (traymenu), pause2); + + image61 = gtk_image_new_from_stock ("gtk-media-pause", GTK_ICON_SIZE_MENU); + gtk_widget_show (image61); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (pause2), image61); + + previous2 = gtk_image_menu_item_new_with_mnemonic ("Previous"); + gtk_widget_show (previous2); + gtk_container_add (GTK_CONTAINER (traymenu), previous2); + + image62 = gtk_image_new_from_stock ("gtk-media-previous", GTK_ICON_SIZE_MENU); + gtk_widget_show (image62); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (previous2), image62); + + next2 = gtk_image_menu_item_new_with_mnemonic ("Next"); + gtk_widget_show (next2); + gtk_container_add (GTK_CONTAINER (traymenu), next2); + + image63 = gtk_image_new_from_stock ("gtk-media-next", GTK_ICON_SIZE_MENU); + gtk_widget_show (image63); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (next2), image63); + + play_random1 = gtk_menu_item_new_with_mnemonic ("Play Random"); + gtk_widget_show (play_random1); + gtk_container_add (GTK_CONTAINER (traymenu), play_random1); + + separator4 = gtk_separator_menu_item_new (); + gtk_widget_show (separator4); + gtk_container_add (GTK_CONTAINER (traymenu), separator4); + gtk_widget_set_sensitive (separator4, FALSE); + + about3 = gtk_image_menu_item_new_with_mnemonic ("About"); + gtk_widget_show (about3); + gtk_container_add (GTK_CONTAINER (traymenu), about3); + + image64 = gtk_image_new_from_stock ("gtk-about", GTK_ICON_SIZE_MENU); + gtk_widget_show (image64); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (about3), image64); + + separator3 = gtk_separator_menu_item_new (); + gtk_widget_show (separator3); + gtk_container_add (GTK_CONTAINER (traymenu), separator3); + gtk_widget_set_sensitive (separator3, FALSE); + + quit = gtk_image_menu_item_new_with_mnemonic ("Quit"); + gtk_widget_show (quit); + gtk_container_add (GTK_CONTAINER (traymenu), quit); + + image65 = gtk_image_new_from_stock ("gtk-quit", GTK_ICON_SIZE_MENU); + gtk_widget_show (image65); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (quit), image65); + + g_signal_connect ((gpointer) stop2, "activate", + G_CALLBACK (on_stopbtn_clicked), + NULL); + g_signal_connect ((gpointer) play2, "activate", + G_CALLBACK (on_playbtn_clicked), + NULL); + g_signal_connect ((gpointer) pause2, "activate", + G_CALLBACK (on_pausebtn_clicked), + NULL); + g_signal_connect ((gpointer) previous2, "activate", + G_CALLBACK (on_prevbtn_clicked), + NULL); + g_signal_connect ((gpointer) next2, "activate", + G_CALLBACK (on_nextbtn_clicked), + NULL); + g_signal_connect ((gpointer) play_random1, "activate", + G_CALLBACK (on_playrand_clicked), + NULL); + g_signal_connect ((gpointer) about3, "activate", + G_CALLBACK (on_about1_activate), + NULL); + g_signal_connect ((gpointer) quit, "activate", + G_CALLBACK (on_quit_activate), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (traymenu, traymenu, "traymenu"); + GLADE_HOOKUP_OBJECT (traymenu, stop2, "stop2"); + GLADE_HOOKUP_OBJECT (traymenu, image59, "image59"); + GLADE_HOOKUP_OBJECT (traymenu, play2, "play2"); + GLADE_HOOKUP_OBJECT (traymenu, image60, "image60"); + GLADE_HOOKUP_OBJECT (traymenu, pause2, "pause2"); + GLADE_HOOKUP_OBJECT (traymenu, image61, "image61"); + GLADE_HOOKUP_OBJECT (traymenu, previous2, "previous2"); + GLADE_HOOKUP_OBJECT (traymenu, image62, "image62"); + GLADE_HOOKUP_OBJECT (traymenu, next2, "next2"); + GLADE_HOOKUP_OBJECT (traymenu, image63, "image63"); + GLADE_HOOKUP_OBJECT (traymenu, play_random1, "play_random1"); + GLADE_HOOKUP_OBJECT (traymenu, separator4, "separator4"); + GLADE_HOOKUP_OBJECT (traymenu, about3, "about3"); + GLADE_HOOKUP_OBJECT (traymenu, image64, "image64"); + GLADE_HOOKUP_OBJECT (traymenu, separator3, "separator3"); + GLADE_HOOKUP_OBJECT (traymenu, quit, "quit"); + GLADE_HOOKUP_OBJECT (traymenu, image65, "image65"); + + return traymenu; +} + +GtkWidget* +create_addprogress (void) +{ + GtkWidget *addprogress; + GtkWidget *vbox6; + GtkWidget *progresstitle; + GtkWidget *hbox7; + GtkWidget *label22; + GtkWidget *button1; + + addprogress = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (addprogress), "Adding files..."); + gtk_window_set_position (GTK_WINDOW (addprogress), GTK_WIN_POS_CENTER_ON_PARENT); + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (addprogress), TRUE); + gtk_window_set_skip_pager_hint (GTK_WINDOW (addprogress), TRUE); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox6); + gtk_container_add (GTK_CONTAINER (addprogress), vbox6); + gtk_container_set_border_width (GTK_CONTAINER (vbox6), 4); + + progresstitle = gtk_entry_new (); + gtk_widget_show (progresstitle); + gtk_box_pack_start (GTK_BOX (vbox6), progresstitle, TRUE, FALSE, 0); + gtk_widget_set_size_request (progresstitle, 500, -1); + GTK_WIDGET_UNSET_FLAGS (progresstitle, GTK_CAN_FOCUS); + gtk_editable_set_editable (GTK_EDITABLE (progresstitle), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (progresstitle), 8226); + + hbox7 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox7); + gtk_box_pack_start (GTK_BOX (vbox6), hbox7, FALSE, TRUE, 2); + + label22 = gtk_label_new (""); + gtk_widget_show (label22); + gtk_box_pack_start (GTK_BOX (hbox7), label22, TRUE, FALSE, 0); + + button1 = gtk_button_new_with_mnemonic ("Abort"); + gtk_widget_show (button1); + gtk_box_pack_start (GTK_BOX (hbox7), button1, FALSE, FALSE, 0); + gtk_widget_set_size_request (button1, 83, -1); + GTK_WIDGET_UNSET_FLAGS (button1, GTK_CAN_FOCUS); + + g_signal_connect ((gpointer) addprogress, "delete_event", + G_CALLBACK (on_addprogress_delete_event), + NULL); + g_signal_connect ((gpointer) button1, "clicked", + G_CALLBACK (on_progress_abort), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (addprogress, addprogress, "addprogress"); + GLADE_HOOKUP_OBJECT (addprogress, vbox6, "vbox6"); + GLADE_HOOKUP_OBJECT (addprogress, progresstitle, "progresstitle"); + GLADE_HOOKUP_OBJECT (addprogress, hbox7, "hbox7"); + GLADE_HOOKUP_OBJECT (addprogress, label22, "label22"); + GLADE_HOOKUP_OBJECT (addprogress, button1, "button1"); + + return addprogress; +} + +GtkWidget* +create_helpwindow (void) +{ + GtkWidget *helpwindow; + GtkWidget *scrolledwindow1; + GtkWidget *helptext; + + helpwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_size_request (helpwindow, 600, 400); + gtk_widget_set_events (helpwindow, GDK_KEY_PRESS_MASK); + gtk_window_set_title (GTK_WINDOW (helpwindow), "Help"); + gtk_window_set_modal (GTK_WINDOW (helpwindow), TRUE); + gtk_window_set_destroy_with_parent (GTK_WINDOW (helpwindow), TRUE); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow1); + gtk_container_add (GTK_CONTAINER (helpwindow), scrolledwindow1); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + helptext = gtk_text_view_new (); + gtk_widget_show (helptext); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), helptext); + gtk_text_view_set_editable (GTK_TEXT_VIEW (helptext), FALSE); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (helptext), GTK_WRAP_WORD); + gtk_text_view_set_left_margin (GTK_TEXT_VIEW (helptext), 10); + gtk_text_view_set_right_margin (GTK_TEXT_VIEW (helptext), 10); + + g_signal_connect ((gpointer) helpwindow, "key_press_event", + G_CALLBACK (on_helpwindow_key_press_event), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (helpwindow, helpwindow, "helpwindow"); + GLADE_HOOKUP_OBJECT (helpwindow, scrolledwindow1, "scrolledwindow1"); + GLADE_HOOKUP_OBJECT (helpwindow, helptext, "helptext"); + + return helpwindow; +} + +GtkWidget* +create_prefwin (void) +{ + GtkWidget *prefwin; + GtkWidget *notebook2; + GtkWidget *table3; + GtkWidget *label4; + GtkWidget *label5; + GtkWidget *label6; + GtkWidget *label8; + GtkWidget *label9; + GtkWidget *label15; + GtkWidget *pref_alsa_resampling; + GtkWidget *pref_replaygain_scale; + GtkWidget *pref_alsa_freewhenstopped; + GtkWidget *pref_soundcard; + GtkWidget *pref_src_quality; + GtkWidget *pref_replaygain_mode; + GtkWidget *Sound; + GtkWidget *table4; + GtkWidget *label7; + GtkWidget *pref_close_send_to_tray; + GtkWidget *label2; + GtkWidget *table6; + GtkWidget *label17; + GtkWidget *label18; + GtkWidget *pref_network_proxyaddress; + GtkWidget *pref_network_enableproxy; + GtkWidget *label19; + GtkWidget *pref_network_proxyport; + GtkWidget *label20; + GtkWidget *pref_network_proxytype; + GtkWidget *label16; + GtkWidget *hpaned1; + GtkWidget *scrolledwindow2; + GtkWidget *pref_pluginlist; + GtkWidget *table5; + GtkWidget *label11; + GtkWidget *label12; + GtkWidget *label13; + GtkWidget *label14; + GtkWidget *pref_plugin_descr; + GtkWidget *pref_plugin_author; + GtkWidget *pref_plugin_email; + GtkWidget *pref_plugin_website; + GtkWidget *label3; + + prefwin = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_size_request (prefwin, 642, 372); + gtk_window_set_title (GTK_WINDOW (prefwin), "Preferences"); + gtk_window_set_modal (GTK_WINDOW (prefwin), TRUE); + + notebook2 = gtk_notebook_new (); + gtk_widget_show (notebook2); + gtk_container_add (GTK_CONTAINER (prefwin), notebook2); + + table3 = gtk_table_new (6, 2, FALSE); + gtk_widget_show (table3); + gtk_container_add (GTK_CONTAINER (notebook2), table3); + gtk_container_set_border_width (GTK_CONTAINER (table3), 3); + gtk_table_set_col_spacings (GTK_TABLE (table3), 3); + + label4 = gtk_label_new ("Output device"); + gtk_widget_show (label4); + gtk_table_attach (GTK_TABLE (table3), label4, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label4), 0, 0.5); + + label5 = gtk_label_new ("Software ALSA resampling"); + gtk_widget_show (label5); + gtk_table_attach (GTK_TABLE (table3), label5, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label5), 0, 0.5); + + label6 = gtk_label_new ("SRC quality (libsamplerate)"); + gtk_widget_show (label6); + gtk_table_attach (GTK_TABLE (table3), label6, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label6), 0, 0.5); + + label8 = gtk_label_new ("Replaygain mode"); + gtk_widget_show (label8); + gtk_table_attach (GTK_TABLE (table3), label8, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label8), 0, 0.5); + + label9 = gtk_label_new ("Replaygain peak scale"); + gtk_widget_show (label9); + gtk_table_attach (GTK_TABLE (table3), label9, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label9), 0, 0.5); + + label15 = gtk_label_new ("Release ALSA while stopped"); + gtk_widget_show (label15); + gtk_table_attach (GTK_TABLE (table3), label15, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label15), 0, 0.5); + + pref_alsa_resampling = gtk_check_button_new_with_mnemonic (""); + gtk_widget_show (pref_alsa_resampling); + gtk_table_attach (GTK_TABLE (table3), pref_alsa_resampling, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + pref_replaygain_scale = gtk_check_button_new_with_mnemonic (""); + gtk_widget_show (pref_replaygain_scale); + gtk_table_attach (GTK_TABLE (table3), pref_replaygain_scale, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + pref_alsa_freewhenstopped = gtk_check_button_new_with_mnemonic (""); + gtk_widget_show (pref_alsa_freewhenstopped); + gtk_table_attach (GTK_TABLE (table3), pref_alsa_freewhenstopped, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + pref_soundcard = gtk_combo_box_new_text (); + gtk_widget_show (pref_soundcard); + gtk_table_attach (GTK_TABLE (table3), pref_soundcard, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + pref_src_quality = gtk_combo_box_new_text (); + gtk_widget_show (pref_src_quality); + gtk_table_attach (GTK_TABLE (table3), pref_src_quality, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_src_quality), "sinc_best_quality"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_src_quality), "sinc_medium_quality"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_src_quality), "sinc_fastest"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_src_quality), "sinc_zero_order_hold"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_src_quality), "linear"); + + pref_replaygain_mode = gtk_combo_box_new_text (); + gtk_widget_show (pref_replaygain_mode); + gtk_table_attach (GTK_TABLE (table3), pref_replaygain_mode, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), "Disable"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), "Track"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), "Album"); + + Sound = gtk_label_new ("Sound"); + gtk_widget_show (Sound); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 0), Sound); + + table4 = gtk_table_new (1, 2, FALSE); + gtk_widget_show (table4); + gtk_container_add (GTK_CONTAINER (notebook2), table4); + gtk_container_set_border_width (GTK_CONTAINER (table4), 3); + gtk_table_set_col_spacings (GTK_TABLE (table4), 3); + + label7 = gtk_label_new ("Close minimizes to tray"); + gtk_widget_show (label7); + gtk_table_attach (GTK_TABLE (table4), label7, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5); + + pref_close_send_to_tray = gtk_check_button_new_with_mnemonic (""); + gtk_widget_show (pref_close_send_to_tray); + gtk_table_attach (GTK_TABLE (table4), pref_close_send_to_tray, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label2 = gtk_label_new ("GUI"); + gtk_widget_show (label2); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 1), label2); + + table6 = gtk_table_new (4, 2, FALSE); + gtk_widget_show (table6); + gtk_container_add (GTK_CONTAINER (notebook2), table6); + gtk_container_set_border_width (GTK_CONTAINER (table6), 3); + gtk_table_set_col_spacings (GTK_TABLE (table6), 3); + + label17 = gtk_label_new ("Enable proxy server"); + gtk_widget_show (label17); + gtk_table_attach (GTK_TABLE (table6), label17, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label17), 0, 0.5); + + label18 = gtk_label_new ("Proxy server address"); + gtk_widget_show (label18); + gtk_table_attach (GTK_TABLE (table6), label18, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label18), 0, 0.5); + + pref_network_proxyaddress = gtk_entry_new (); + gtk_widget_show (pref_network_proxyaddress); + gtk_table_attach (GTK_TABLE (table6), pref_network_proxyaddress, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (pref_network_proxyaddress), 8226); + + pref_network_enableproxy = gtk_check_button_new_with_mnemonic (""); + gtk_widget_show (pref_network_enableproxy); + gtk_table_attach (GTK_TABLE (table6), pref_network_enableproxy, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label19 = gtk_label_new ("Proxy server port"); + gtk_widget_show (label19); + gtk_table_attach (GTK_TABLE (table6), label19, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label19), 0, 0.5); + + pref_network_proxyport = gtk_entry_new (); + gtk_widget_show (pref_network_proxyport); + gtk_table_attach (GTK_TABLE (table6), pref_network_proxyport, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (pref_network_proxyport), 8226); + + label20 = gtk_label_new ("Proxy type"); + gtk_widget_show (label20); + gtk_table_attach (GTK_TABLE (table6), label20, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label20), 0, 0.5); + + pref_network_proxytype = gtk_combo_box_new_text (); + gtk_widget_show (pref_network_proxytype); + gtk_table_attach (GTK_TABLE (table6), pref_network_proxytype, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_network_proxytype), "HTTP"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_network_proxytype), "HTTP_1_0"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_network_proxytype), "SOCKS4"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_network_proxytype), "SOCKS5"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_network_proxytype), "SOCKS4A"); + gtk_combo_box_append_text (GTK_COMBO_BOX (pref_network_proxytype), "SOCKS5_HOSTNAME"); + + label16 = gtk_label_new ("Network"); + gtk_widget_show (label16); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 2), label16); + + hpaned1 = gtk_hpaned_new (); + gtk_widget_show (hpaned1); + gtk_container_add (GTK_CONTAINER (notebook2), hpaned1); + + scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow2); + gtk_paned_pack1 (GTK_PANED (hpaned1), scrolledwindow2, FALSE, TRUE); + gtk_widget_set_size_request (scrolledwindow2, 280, -1); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_SHADOW_IN); + + pref_pluginlist = gtk_tree_view_new (); + gtk_widget_show (pref_pluginlist); + gtk_container_add (GTK_CONTAINER (scrolledwindow2), pref_pluginlist); + + table5 = gtk_table_new (4, 2, FALSE); + gtk_widget_show (table5); + gtk_paned_pack2 (GTK_PANED (hpaned1), table5, TRUE, TRUE); + gtk_widget_set_size_request (table5, 400, -1); + + label11 = gtk_label_new ("Description"); + gtk_widget_show (label11); + gtk_table_attach (GTK_TABLE (table5), label11, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label11), 0, 0.5); + + label12 = gtk_label_new ("Author(s)"); + gtk_widget_show (label12); + gtk_table_attach (GTK_TABLE (table5), label12, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label12), 0, 0.5); + + label13 = gtk_label_new ("Email"); + gtk_widget_show (label13); + gtk_table_attach (GTK_TABLE (table5), label13, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label13), 0, 0.5); + + label14 = gtk_label_new ("Website"); + gtk_widget_show (label14); + gtk_table_attach (GTK_TABLE (table5), label14, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label14), 0, 0.5); + + pref_plugin_descr = gtk_entry_new (); + gtk_widget_show (pref_plugin_descr); + gtk_table_attach (GTK_TABLE (table5), pref_plugin_descr, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_editable_set_editable (GTK_EDITABLE (pref_plugin_descr), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (pref_plugin_descr), 9679); + + pref_plugin_author = gtk_entry_new (); + gtk_widget_show (pref_plugin_author); + gtk_table_attach (GTK_TABLE (table5), pref_plugin_author, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_editable_set_editable (GTK_EDITABLE (pref_plugin_author), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (pref_plugin_author), 9679); + + pref_plugin_email = gtk_entry_new (); + gtk_widget_show (pref_plugin_email); + gtk_table_attach (GTK_TABLE (table5), pref_plugin_email, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_editable_set_editable (GTK_EDITABLE (pref_plugin_email), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (pref_plugin_email), 9679); + + pref_plugin_website = gtk_entry_new (); + gtk_widget_show (pref_plugin_website); + gtk_table_attach (GTK_TABLE (table5), pref_plugin_website, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_editable_set_editable (GTK_EDITABLE (pref_plugin_website), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (pref_plugin_website), 9679); + + label3 = gtk_label_new ("Plugins"); + gtk_widget_show (label3); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 3), label3); + + g_signal_connect ((gpointer) prefwin, "key_press_event", + G_CALLBACK (on_prefwin_key_press_event), + NULL); + g_signal_connect ((gpointer) pref_alsa_resampling, "clicked", + G_CALLBACK (on_pref_alsa_resampling_clicked), + NULL); + g_signal_connect ((gpointer) pref_replaygain_scale, "clicked", + G_CALLBACK (on_pref_replaygain_scale_clicked), + NULL); + g_signal_connect ((gpointer) pref_alsa_freewhenstopped, "clicked", + G_CALLBACK (on_pref_alsa_freewhenstopped_clicked), + NULL); + g_signal_connect ((gpointer) pref_soundcard, "changed", + G_CALLBACK (on_pref_soundcard_changed), + NULL); + g_signal_connect ((gpointer) pref_src_quality, "changed", + G_CALLBACK (on_pref_src_quality_changed), + NULL); + g_signal_connect ((gpointer) pref_replaygain_mode, "changed", + G_CALLBACK (on_pref_replaygain_mode_changed), + NULL); + g_signal_connect ((gpointer) pref_close_send_to_tray, "clicked", + G_CALLBACK (on_pref_close_send_to_tray_clicked), + NULL); + g_signal_connect ((gpointer) pref_network_proxyaddress, "changed", + G_CALLBACK (on_pref_network_proxyaddress_changed), + NULL); + g_signal_connect ((gpointer) pref_network_enableproxy, "clicked", + G_CALLBACK (on_pref_network_enableproxy_clicked), + NULL); + g_signal_connect ((gpointer) pref_network_proxyport, "changed", + G_CALLBACK (on_pref_network_proxyport_changed), + NULL); + g_signal_connect ((gpointer) pref_network_proxytype, "changed", + G_CALLBACK (on_pref_network_proxytype_changed), + NULL); + g_signal_connect ((gpointer) pref_pluginlist, "cursor_changed", + G_CALLBACK (on_pref_pluginlist_cursor_changed), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (prefwin, prefwin, "prefwin"); + GLADE_HOOKUP_OBJECT (prefwin, notebook2, "notebook2"); + GLADE_HOOKUP_OBJECT (prefwin, table3, "table3"); + GLADE_HOOKUP_OBJECT (prefwin, label4, "label4"); + GLADE_HOOKUP_OBJECT (prefwin, label5, "label5"); + GLADE_HOOKUP_OBJECT (prefwin, label6, "label6"); + GLADE_HOOKUP_OBJECT (prefwin, label8, "label8"); + GLADE_HOOKUP_OBJECT (prefwin, label9, "label9"); + GLADE_HOOKUP_OBJECT (prefwin, label15, "label15"); + GLADE_HOOKUP_OBJECT (prefwin, pref_alsa_resampling, "pref_alsa_resampling"); + GLADE_HOOKUP_OBJECT (prefwin, pref_replaygain_scale, "pref_replaygain_scale"); + GLADE_HOOKUP_OBJECT (prefwin, pref_alsa_freewhenstopped, "pref_alsa_freewhenstopped"); + GLADE_HOOKUP_OBJECT (prefwin, pref_soundcard, "pref_soundcard"); + GLADE_HOOKUP_OBJECT (prefwin, pref_src_quality, "pref_src_quality"); + GLADE_HOOKUP_OBJECT (prefwin, pref_replaygain_mode, "pref_replaygain_mode"); + GLADE_HOOKUP_OBJECT (prefwin, Sound, "Sound"); + GLADE_HOOKUP_OBJECT (prefwin, table4, "table4"); + GLADE_HOOKUP_OBJECT (prefwin, label7, "label7"); + GLADE_HOOKUP_OBJECT (prefwin, pref_close_send_to_tray, "pref_close_send_to_tray"); + GLADE_HOOKUP_OBJECT (prefwin, label2, "label2"); + GLADE_HOOKUP_OBJECT (prefwin, table6, "table6"); + GLADE_HOOKUP_OBJECT (prefwin, label17, "label17"); + GLADE_HOOKUP_OBJECT (prefwin, label18, "label18"); + GLADE_HOOKUP_OBJECT (prefwin, pref_network_proxyaddress, "pref_network_proxyaddress"); + GLADE_HOOKUP_OBJECT (prefwin, pref_network_enableproxy, "pref_network_enableproxy"); + GLADE_HOOKUP_OBJECT (prefwin, label19, "label19"); + GLADE_HOOKUP_OBJECT (prefwin, pref_network_proxyport, "pref_network_proxyport"); + GLADE_HOOKUP_OBJECT (prefwin, label20, "label20"); + GLADE_HOOKUP_OBJECT (prefwin, pref_network_proxytype, "pref_network_proxytype"); + GLADE_HOOKUP_OBJECT (prefwin, label16, "label16"); + GLADE_HOOKUP_OBJECT (prefwin, hpaned1, "hpaned1"); + GLADE_HOOKUP_OBJECT (prefwin, scrolledwindow2, "scrolledwindow2"); + GLADE_HOOKUP_OBJECT (prefwin, pref_pluginlist, "pref_pluginlist"); + GLADE_HOOKUP_OBJECT (prefwin, table5, "table5"); + GLADE_HOOKUP_OBJECT (prefwin, label11, "label11"); + GLADE_HOOKUP_OBJECT (prefwin, label12, "label12"); + GLADE_HOOKUP_OBJECT (prefwin, label13, "label13"); + GLADE_HOOKUP_OBJECT (prefwin, label14, "label14"); + GLADE_HOOKUP_OBJECT (prefwin, pref_plugin_descr, "pref_plugin_descr"); + GLADE_HOOKUP_OBJECT (prefwin, pref_plugin_author, "pref_plugin_author"); + GLADE_HOOKUP_OBJECT (prefwin, pref_plugin_email, "pref_plugin_email"); + GLADE_HOOKUP_OBJECT (prefwin, pref_plugin_website, "pref_plugin_website"); + GLADE_HOOKUP_OBJECT (prefwin, label3, "label3"); + + return prefwin; +} + +GtkWidget* +create_headermenu (void) +{ + GtkWidget *headermenu; + GtkWidget *add_column; + GtkWidget *add_column_menu; + GtkWidget *artist; + GtkWidget *album; + GtkWidget *tracknum; + GtkWidget *duration; + GtkWidget *playing; + GtkWidget *title; + GtkWidget *separator7; + GtkWidget *custom; + GtkWidget *remove_column; + + headermenu = gtk_menu_new (); + + add_column = gtk_menu_item_new_with_mnemonic ("Add column"); + gtk_widget_show (add_column); + gtk_container_add (GTK_CONTAINER (headermenu), add_column); + + add_column_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (add_column), add_column_menu); + + artist = gtk_menu_item_new_with_mnemonic ("Artist"); + gtk_widget_show (artist); + gtk_container_add (GTK_CONTAINER (add_column_menu), artist); + + album = gtk_menu_item_new_with_mnemonic ("Album"); + gtk_widget_show (album); + gtk_container_add (GTK_CONTAINER (add_column_menu), album); + + tracknum = gtk_menu_item_new_with_mnemonic ("Track number"); + gtk_widget_show (tracknum); + gtk_container_add (GTK_CONTAINER (add_column_menu), tracknum); + + duration = gtk_menu_item_new_with_mnemonic ("Duration"); + gtk_widget_show (duration); + gtk_container_add (GTK_CONTAINER (add_column_menu), duration); + + playing = gtk_menu_item_new_with_mnemonic ("Playing status"); + gtk_widget_show (playing); + gtk_container_add (GTK_CONTAINER (add_column_menu), playing); + + title = gtk_menu_item_new_with_mnemonic ("Title"); + gtk_widget_show (title); + gtk_container_add (GTK_CONTAINER (add_column_menu), title); + + separator7 = gtk_separator_menu_item_new (); + gtk_widget_show (separator7); + gtk_container_add (GTK_CONTAINER (add_column_menu), separator7); + gtk_widget_set_sensitive (separator7, FALSE); + + custom = gtk_menu_item_new_with_mnemonic ("Custom"); + gtk_widget_show (custom); + gtk_container_add (GTK_CONTAINER (add_column_menu), custom); + + remove_column = gtk_menu_item_new_with_mnemonic ("Remove this column"); + gtk_widget_show (remove_column); + gtk_container_add (GTK_CONTAINER (headermenu), remove_column); + + g_signal_connect ((gpointer) artist, "activate", + G_CALLBACK (on_artist_activate), + NULL); + g_signal_connect ((gpointer) album, "activate", + G_CALLBACK (on_album_activate), + NULL); + g_signal_connect ((gpointer) tracknum, "activate", + G_CALLBACK (on_tracknum_activate), + NULL); + g_signal_connect ((gpointer) duration, "activate", + G_CALLBACK (on_duration_activate), + NULL); + g_signal_connect ((gpointer) playing, "activate", + G_CALLBACK (on_playing_activate), + NULL); + g_signal_connect ((gpointer) title, "activate", + G_CALLBACK (on_title_activate), + NULL); + g_signal_connect ((gpointer) custom, "activate", + G_CALLBACK (on_custom_activate), + NULL); + g_signal_connect ((gpointer) remove_column, "activate", + G_CALLBACK (on_remove_column_activate), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (headermenu, headermenu, "headermenu"); + GLADE_HOOKUP_OBJECT (headermenu, add_column, "add_column"); + GLADE_HOOKUP_OBJECT (headermenu, add_column_menu, "add_column_menu"); + GLADE_HOOKUP_OBJECT (headermenu, artist, "artist"); + GLADE_HOOKUP_OBJECT (headermenu, album, "album"); + GLADE_HOOKUP_OBJECT (headermenu, tracknum, "tracknum"); + GLADE_HOOKUP_OBJECT (headermenu, duration, "duration"); + GLADE_HOOKUP_OBJECT (headermenu, playing, "playing"); + GLADE_HOOKUP_OBJECT (headermenu, title, "title"); + GLADE_HOOKUP_OBJECT (headermenu, separator7, "separator7"); + GLADE_HOOKUP_OBJECT (headermenu, custom, "custom"); + GLADE_HOOKUP_OBJECT (headermenu, remove_column, "remove_column"); + + return headermenu; +} + +GtkWidget* +create_addlocation (void) +{ + GtkWidget *addlocation; + GtkWidget *vbox7; + GtkWidget *addlocation_entry; + GtkWidget *hbox8; + GtkWidget *label21; + GtkWidget *addlocation_ok; + + addlocation = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (addlocation), "Add Location"); + gtk_window_set_modal (GTK_WINDOW (addlocation), TRUE); + gtk_window_set_destroy_with_parent (GTK_WINDOW (addlocation), TRUE); + + vbox7 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox7); + gtk_container_add (GTK_CONTAINER (addlocation), vbox7); + gtk_container_set_border_width (GTK_CONTAINER (vbox7), 4); + + addlocation_entry = gtk_entry_new (); + gtk_widget_show (addlocation_entry); + gtk_box_pack_start (GTK_BOX (vbox7), addlocation_entry, FALSE, FALSE, 0); + gtk_widget_set_size_request (addlocation_entry, 346, -1); + gtk_entry_set_invisible_char (GTK_ENTRY (addlocation_entry), 8226); + + hbox8 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox8); + gtk_box_pack_start (GTK_BOX (vbox7), hbox8, FALSE, TRUE, 2); + + label21 = gtk_label_new (""); + gtk_widget_show (label21); + gtk_box_pack_start (GTK_BOX (hbox8), label21, TRUE, FALSE, 0); + + addlocation_ok = gtk_button_new_with_mnemonic ("OK"); + gtk_widget_show (addlocation_ok); + gtk_box_pack_start (GTK_BOX (hbox8), addlocation_ok, FALSE, FALSE, 0); + gtk_widget_set_size_request (addlocation_ok, 83, -1); + GTK_WIDGET_UNSET_FLAGS (addlocation_ok, GTK_CAN_FOCUS); + + g_signal_connect ((gpointer) addlocation, "key_press_event", + G_CALLBACK (on_addlocation_key_press_event), + NULL); + g_signal_connect ((gpointer) addlocation_entry, "activate", + G_CALLBACK (on_addlocation_entry_activate), + NULL); + g_signal_connect ((gpointer) addlocation_ok, "clicked", + G_CALLBACK (on_addlocation_ok_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (addlocation, addlocation, "addlocation"); + GLADE_HOOKUP_OBJECT (addlocation, vbox7, "vbox7"); + GLADE_HOOKUP_OBJECT (addlocation, addlocation_entry, "addlocation_entry"); + GLADE_HOOKUP_OBJECT (addlocation, hbox8, "hbox8"); + GLADE_HOOKUP_OBJECT (addlocation, label21, "label21"); + GLADE_HOOKUP_OBJECT (addlocation, addlocation_ok, "addlocation_ok"); + + return addlocation; +} + diff --git a/plugins/gtkui/interface.h b/plugins/gtkui/interface.h new file mode 100644 index 00000000..f9b470ff --- /dev/null +++ b/plugins/gtkui/interface.h @@ -0,0 +1,12 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_mainwin (void); +GtkWidget* create_searchwin (void); +GtkWidget* create_traymenu (void); +GtkWidget* create_addprogress (void); +GtkWidget* create_helpwindow (void); +GtkWidget* create_prefwin (void); +GtkWidget* create_headermenu (void); +GtkWidget* create_addlocation (void); |