Mercurial > audlegacy
changeset 1644:a556e7ff1871 trunk
[svn] - keep filepopup code in the core for now
- add README noting that this code sucks
- still a ways to go
line wrap: on
line diff
--- a/ChangeLog Thu Sep 07 19:57:27 2006 -0700 +++ b/ChangeLog Thu Sep 07 20:27:46 2006 -0700 @@ -1,3 +1,11 @@ +2006-09-08 02:57:27 +0000 William Pitcock <nenolod@nenolod.net> + revision [2217] + - copy the WA2GUI code into a Plugin shell + + + Changes: Modified: + + 2006-09-08 01:33:19 +0000 William Pitcock <nenolod@nenolod.net> revision [2215] - use gdk_drawable_get_size() instead
--- a/Plugins/UserInterface/wa2gui/Makefile Thu Sep 07 19:57:27 2006 -0700 +++ b/Plugins/UserInterface/wa2gui/Makefile Thu Sep 07 20:27:46 2006 -0700 @@ -1,14 +1,16 @@ include ../../../mk/rules.mk include ../../../mk/init.mk -OBJECTIVE_LIBS = libwa2_gui$(SHARED_SUFFIX) +OBJECTIVE_LIBS = libwa2gui$(SHARED_SUFFIX) + +SUBDIRS = widgets noinst_HEADERS = coreaudio.h LIBDIR = $(plugindir)/$(USERINTERFACE_PLUGIN_DIR) LIBADD = $(GTK_LIBS) -SOURCES = mainwin.c equalizer.c playlist.c filepopup.c wa2gui.c +SOURCES = mainwin.c equalizer.c playlist.c wa2gui.c OBJECTS = ${SOURCES:.c=.o}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/README Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,9 @@ +This is the XMMS/BMP WA2GUI implementation. + +It is broken on everything other than X11, so don't expect it to work on your platform. +Thanks! + +If you want to fix or rewrite it, be our guest! + +Toodles now. + - audacious team
--- a/Plugins/UserInterface/wa2gui/equalizer.c Thu Sep 07 19:57:27 2006 -0700 +++ b/Plugins/UserInterface/wa2gui/equalizer.c Thu Sep 07 20:27:46 2006 -0700 @@ -27,6 +27,7 @@ #endif #include "equalizer.h" +#include "playlist.h" #include <glib.h> #include <glib/gi18n.h> @@ -35,21 +36,20 @@ #include <math.h> #include <string.h> -#include "platform/smartinclude.h" -#include "widgets/widgetcore.h" -#include "dock.h" -#include "hints.h" -#include "input.h" -#include "main.h" -#include "playlist.h" -#include "ui_playlist.h" -#include "util.h" -#include "output.h" +#include "audacious/platform/smartinclude.h" +#include "audacious/widgets/widgetcore.h" +#include "audacious/dock.h" +#include "audacious/hints.h" +#include "audacious/input.h" +#include "audacious/main.h" +#include "audacious/playlist.h" +#include "audacious/util.h" +#include "audacious/output.h" #include "libaudacious/rcfile.h" #include "libaudacious/vfs.h" -#include "images/audacious_eq.xpm" +#include "audacious/images/audacious_eq.xpm" enum PresetViewCols { PRESET_VIEW_COL_NAME,
--- a/Plugins/UserInterface/wa2gui/equalizer.h Thu Sep 07 19:57:27 2006 -0700 +++ b/Plugins/UserInterface/wa2gui/equalizer.h Thu Sep 07 20:27:46 2006 -0700 @@ -25,7 +25,7 @@ #include <glib.h> #include <gtk/gtk.h> -#include "widgets/widgetcore.h" +#include "audacious/widgets/widgetcore.h" #define EQUALIZER_HEIGHT (gint)(cfg.equalizer_shaded ? 14 : 116) #define EQUALIZER_WIDTH (gint)275
--- a/Plugins/UserInterface/wa2gui/filepopup.c Thu Sep 07 19:57:27 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,512 +0,0 @@ -/* - * Audacious: A cross-platform multimedia player - * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill, - * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa. - * - * 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 <glib.h> -#include <glib/gi18n.h> -#include <gtk/gtk.h> -#include <glade/glade.h> -#include <string.h> -#include <stddef.h> -#include <stdio.h> -#include <sys/types.h> -#include <dirent.h> -#include <unistd.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "glade.h" - -#include "plugin.h" -#include "pluginenum.h" -#include "input.h" -#include "effect.h" -#include "general.h" -#include "output.h" -#include "visualization.h" - -#include "main.h" -#include "urldecode.h" -#include "util.h" -#include "dnd.h" -#include "libaudacious/configdb.h" -#include "libaudacious/titlestring.h" - -#include "playlist.h" - -#include "mainwin.h" -#include "ui_playlist.h" -#include "skinwin.h" -#include "build_stamp.h" -#include "ui_fileinfo.h" -#include "ui_playlist.h" - -GtkWidget *fileinfo_win; -GtkWidget *filepopup_win; -GdkPixbuf *filepopup_pixbuf; - -static void -fileinfo_entry_set_text(const char *entry, const char *text) -{ - GladeXML *xml = g_object_get_data(G_OBJECT(fileinfo_win), "glade-xml"); - GtkWidget *widget = glade_xml_get_widget(xml, entry); - - if (xml == NULL || widget == NULL) - return; - - gtk_entry_set_text(GTK_ENTRY(widget), text); -} - -static void -fileinfo_entry_set_text_free(const char *entry, char *text) -{ - GladeXML *xml = g_object_get_data(G_OBJECT(fileinfo_win), "glade-xml"); - GtkWidget *widget = glade_xml_get_widget(xml, entry); - - if (xml == NULL || widget == NULL) - return; - - gtk_entry_set_text(GTK_ENTRY(widget), text); - - g_free(text); -} - -static void -fileinfo_entry_set_image(const char *entry, const char *text) -{ - GladeXML *xml = g_object_get_data(G_OBJECT(fileinfo_win), "glade-xml"); - GtkWidget *widget = glade_xml_get_widget(xml, entry); - GdkPixbuf *pixbuf; - - if (xml == NULL || widget == NULL) - return; - - pixbuf = gdk_pixbuf_new_from_file(text, NULL); - - if (pixbuf == NULL) - return; - - if (gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf)) > 150) - { - GdkPixbuf *pixbuf2 = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), 150, 150, GDK_INTERP_BILINEAR); - g_object_unref(G_OBJECT(pixbuf)); - pixbuf = pixbuf2; - } - - gtk_image_set_from_pixbuf(GTK_IMAGE(widget), GDK_PIXBUF(pixbuf)); - g_object_unref(G_OBJECT(pixbuf)); -} - -static void -filepopup_entry_set_text(const char *entry, const char *text) -{ - GladeXML *xml = g_object_get_data(G_OBJECT(filepopup_win), "glade-xml"); - GtkWidget *widget = glade_xml_get_widget(xml, entry); - - if (xml == NULL || widget == NULL) - return; - - gtk_label_set_text(GTK_LABEL(widget), text); -} - -static void -filepopup_entry_set_image(const char *entry, const char *text) -{ - GladeXML *xml = g_object_get_data(G_OBJECT(filepopup_win), "glade-xml"); - GtkWidget *widget = glade_xml_get_widget(xml, entry); - GdkPixbuf *pixbuf; - - if (xml == NULL || widget == NULL) - return; - - pixbuf = gdk_pixbuf_new_from_file(text, NULL); - - if (pixbuf == NULL) - return; - - if (gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf)) > 150) - { - GdkPixbuf *pixbuf2 = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), 150, 150, GDK_INTERP_BILINEAR); - g_object_unref(G_OBJECT(pixbuf)); - pixbuf = pixbuf2; - } - - gtk_image_set_from_pixbuf(GTK_IMAGE(widget), GDK_PIXBUF(pixbuf)); - g_object_unref(G_OBJECT(pixbuf)); -} - -static void -filepopup_entry_set_text_free(const char *entry, char *text) -{ - GladeXML *xml = g_object_get_data(G_OBJECT(filepopup_win), "glade-xml"); - GtkWidget *widget = glade_xml_get_widget(xml, entry); - - if (xml == NULL || widget == NULL) - return; - - gtk_label_set_text(GTK_LABEL(widget), text); - - g_free(text); -} - -static gboolean -filepopup_pointer_check_iter(gpointer unused) -{ - gint x, y, pos; - TitleInput *tuple; - static gint prev_x = 0, prev_y = 0, ctr = 0, prev_pos = -1; - gboolean skip = FALSE; - GdkWindow *win; - - win = gdk_window_at_pointer(NULL, NULL); - gdk_window_get_pointer(GDK_WINDOW(playlistwin->window), &x, &y, NULL); - pos = playlist_list_get_playlist_position(playlistwin_list, x, y); - - if (win == NULL - || cfg.show_filepopup_for_tuple == FALSE - || playlistwin_list->pl_tooltips == FALSE - || pos != prev_pos - || win != GDK_WINDOW(playlistwin->window) - || playlistwin_is_shaded()) - { - prev_pos = pos; - ctr = 0; - if ( filepopup_win->window != NULL && - gdk_window_is_viewable(GDK_WINDOW(filepopup_win->window)) ) - filepopup_hide(NULL); - return TRUE; - } - - if (prev_x == x && prev_y == y) - ctr++; - else - { - ctr = 0; - prev_x = x; - prev_y = y; - filepopup_hide(NULL); - return TRUE; - } - - if (filepopup_win->window == NULL) - skip = TRUE; - - if (ctr >= 20 && (skip == TRUE || gdk_window_is_viewable(GDK_WINDOW(filepopup_win->window)) != TRUE)) - { - if (pos == -1) - { - filepopup_hide(NULL); - return TRUE; - } - - prev_pos = pos; - - tuple = playlist_get_tuple(pos); - filepopup_show_for_tuple(tuple); - } - - return TRUE; -} - -void fileinfo_hide(gpointer unused) -{ - gtk_widget_hide(fileinfo_win); - - /* Clear it out. */ - fileinfo_entry_set_text("entry_title", ""); - fileinfo_entry_set_text("entry_artist", ""); - fileinfo_entry_set_text("entry_album", ""); - fileinfo_entry_set_text("entry_comment", ""); - fileinfo_entry_set_text("entry_genre", ""); - fileinfo_entry_set_text("entry_year", ""); - fileinfo_entry_set_text("entry_track", ""); - fileinfo_entry_set_text("entry_location", ""); - - fileinfo_entry_set_image("image_artwork", DATA_DIR "/images/audio.png"); -} - -void filepopup_hide(gpointer unused) -{ - gtk_widget_hide(filepopup_win); - - filepopup_entry_set_text("label_title", ""); - filepopup_entry_set_text("label_artist", ""); - filepopup_entry_set_text("label_album", ""); - filepopup_entry_set_text("label_genre", ""); - filepopup_entry_set_text("label_track", ""); - filepopup_entry_set_text("label_year", ""); - filepopup_entry_set_text("label_length", ""); - - filepopup_entry_set_image("image_artwork", DATA_DIR "/images/audio.png"); - - gtk_window_resize(GTK_WINDOW(filepopup_win), 1, 1); -} - -void -create_fileinfo_window(void) -{ - const gchar *glade_file = DATA_DIR "/glade/fileinfo.glade"; - GladeXML *xml; - GtkWidget *widget; - - xml = glade_xml_new_or_die(_("Track Information Window"), glade_file, NULL, NULL); - - glade_xml_signal_autoconnect(xml); - - fileinfo_win = glade_xml_get_widget(xml, "fileinfo_win"); - g_object_set_data(G_OBJECT(fileinfo_win), "glade-xml", xml); - gtk_window_set_transient_for(GTK_WINDOW(fileinfo_win), GTK_WINDOW(mainwin)); - - widget = glade_xml_get_widget(xml, "image_artwork"); - gtk_image_set_from_file(GTK_IMAGE(widget), DATA_DIR "/images/audio.png"); - - widget = glade_xml_get_widget(xml, "btn_close"); - g_signal_connect(G_OBJECT(widget), "clicked", (GCallback) fileinfo_hide, NULL); -} - -void -create_filepopup_window(void) -{ - const gchar *glade_file = DATA_DIR "/glade/fileinfo_popup.glade"; - GladeXML *xml; - GtkWidget *widget; - - xml = glade_xml_new_or_die(_("Track Information Popup"), glade_file, NULL, NULL); - - glade_xml_signal_autoconnect(xml); - - filepopup_win = glade_xml_get_widget(xml, "win_pl_popup"); - g_object_set_data(G_OBJECT(filepopup_win), "glade-xml", xml); - gtk_window_set_transient_for(GTK_WINDOW(filepopup_win), GTK_WINDOW(mainwin)); - - widget = glade_xml_get_widget(xml, "image_artwork"); - gtk_image_set_from_file(GTK_IMAGE(widget), DATA_DIR "/images/audio.png"); - - g_timeout_add(50, filepopup_pointer_check_iter, NULL); -} - -void -fileinfo_show_for_tuple(TitleInput *tuple) -{ - gchar *tmp = NULL; - - if (tuple == NULL) - return; - - gtk_widget_realize(fileinfo_win); - - fileinfo_entry_set_text("entry_title", tuple->track_name); - fileinfo_entry_set_text("entry_artist", tuple->performer); - fileinfo_entry_set_text("entry_album", tuple->album_name); - fileinfo_entry_set_text("entry_comment", tuple->comment); - fileinfo_entry_set_text("entry_genre", tuple->genre); - - tmp = g_strdup_printf("%s/%s", tuple->file_path, tuple->file_name); - if(tmp){ - fileinfo_entry_set_text_free("entry_location", str_to_utf8(tmp)); - g_free(tmp); - tmp = NULL; - } - - if (tuple->year != 0) - fileinfo_entry_set_text_free("entry_year", g_strdup_printf("%d", tuple->year)); - - if (tuple->track_number != 0) - fileinfo_entry_set_text_free("entry_track", g_strdup_printf("%d", tuple->track_number)); - - tmp = fileinfo_recursive_get_image(tuple->file_path, 0); - - if(tmp) - { - fileinfo_entry_set_image("image_artwork", tmp); - g_free(tmp); - } - - gtk_widget_show(fileinfo_win); -} - -static gboolean -cover_name_filter(const gchar *name, const gchar *filter, const gboolean ret_on_empty) -{ - gboolean result = FALSE; - gchar **splitted; - gchar *current; - gchar *lname; - gint i; - - if (!filter || strlen(filter) == 0) { - return ret_on_empty; - } - - splitted = g_strsplit(filter, ",", 0); - - lname = g_strdup(name); - g_strdown(lname); - - for (i = 0; !result && (current = splitted[i]); i++) { - gchar *stripped = g_strstrip(g_strdup(current)); - g_strdown(stripped); - - result = result || strstr(lname, stripped); - - g_free(stripped); - } - - g_free(lname); - g_strfreev(splitted); - - return result; -} - -/* Check wether it's an image we want */ -static gboolean -is_front_cover_image(const gchar *name) -{ - char *ext; - - ext = strrchr(name, '.'); - if (!ext) { - /* No file extension */ - return FALSE; - } - - if (g_strcasecmp(ext, ".jpg") != 0 && - g_strcasecmp(ext, ".jpeg") != 0 && - g_strcasecmp(ext, ".png") != 0) { - /* No recognized file extension */ - return FALSE; - } - - return cover_name_filter(name, cfg.cover_name_include, TRUE) && - !cover_name_filter(name, cfg.cover_name_exclude, FALSE); -} - -gchar* -fileinfo_recursive_get_image(const gchar* path, gint depth) -{ - GDir *d; - - if (cfg.recurse_for_cover && depth > cfg.recurse_for_cover_depth) - return NULL; - - d = g_dir_open(path, 0, NULL); - - if (d) - { - const gchar *f = g_dir_read_name(d); - - while (f) - { - gchar *newpath = g_strdup_printf("%s/%s", path, f); - - if (is_front_cover_image(f)) - { - /* We found a suitable file in the current - * directory, use that. The string will be - * freed by the caller */ - g_dir_close(d); - return newpath; - } - else - { - f = g_dir_read_name(d); - if (cfg.recurse_for_cover) - { - /* File/directory wasn't suitable, try and recurse into it. - * This should either return a filename for a image file, - * or NULL if there was no suitable file, or 'f' wasn't a dir. - */ - gchar *tmp = fileinfo_recursive_get_image(newpath, depth+1); - - if(tmp) - { - g_free(newpath); - g_dir_close(d); - return tmp; - } - } - } - } - - g_dir_close(d); - } - - return NULL; -} - -void -filepopup_show_for_tuple(TitleInput *tuple) -{ - gchar *tmp; - gint x, y, x_off = 3, y_off = 3, h, w; - - if (tuple == NULL) - return; - - gtk_widget_realize(filepopup_win); - - filepopup_entry_set_text("label_title", tuple->track_name); - filepopup_entry_set_text("label_artist", tuple->performer); - filepopup_entry_set_text("label_album", tuple->album_name); - filepopup_entry_set_text("label_genre", tuple->genre); - - if (tuple->length != -1) - filepopup_entry_set_text_free("label_length", g_strdup_printf("%d:%02d", tuple->length / 60000, (tuple->length / 1000) % 60)); - - if (tuple->year != 0) - filepopup_entry_set_text_free("label_year", g_strdup_printf("%d", tuple->year)); - - if (tuple->track_number != 0) - filepopup_entry_set_text_free("label_track", g_strdup_printf("%d", tuple->track_number)); - - tmp = fileinfo_recursive_get_image(tuple->file_path, 0); - - if(tmp) - { - filepopup_entry_set_image("image_artwork", tmp); - g_free(tmp); - } - - gdk_window_get_pointer(NULL, &x, &y, NULL); - gtk_window_get_size(GTK_WINDOW(filepopup_win), &w, &h); - if (gdk_screen_width()-(w+3) < x) x_off = (w*-1)-3; - if (gdk_screen_height()-(h+3) < y) y_off = (h*-1)-3; - gtk_window_move(GTK_WINDOW(filepopup_win), x + x_off, y + y_off); - - gtk_widget_show(filepopup_win); -} - -void -fileinfo_show_for_path(gchar *path) -{ - TitleInput *tuple = input_get_song_tuple(path); - - if (tuple == NULL) - return input_file_info_box(path); - - fileinfo_show_for_tuple(tuple); - - bmp_title_input_free(tuple); - tuple = NULL; -}
--- a/Plugins/UserInterface/wa2gui/filepopup.h Thu Sep 07 19:57:27 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Audacious: A cross-platform multimedia player - * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill, - * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa. - * - * 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 _UI_FILEINFO_H_ -#define _UI_FILEINFO_H_ - -void create_fileinfo_window(void); -void create_filepopup_window(void); -void fileinfo_show_for_tuple(TitleInput *tuple); -void filepopup_show_for_tuple(TitleInput *tuple); -gchar* fileinfo_recursive_get_image(const gchar* path, gint depth); -void fileinfo_show_for_path(gchar *path); - -void filepopup_hide(gpointer unused); - -#endif
--- a/Plugins/UserInterface/wa2gui/mainwin.c Thu Sep 07 19:57:27 2006 -0700 +++ b/Plugins/UserInterface/wa2gui/mainwin.c Thu Sep 07 20:27:46 2006 -0700 @@ -34,7 +34,7 @@ #include <gtk/gtkmessagedialog.h> /* GDK including */ -#include "platform/smartinclude.h" +#include "audacious/platform/smartinclude.h" #include <math.h> #include <stdlib.h> @@ -42,31 +42,32 @@ #include <X11/Xlib.h> -#include "widgets/widgetcore.h" +#include "audacious/widgets/widgetcore.h" #include "mainwin.h" -#include "pixmaps.h" - -#include "main.h" - -#include "controlsocket.h" -#include "pluginenum.h" - -#include "credits.h" -#include "dnd.h" -#include "dock.h" +#include "audacious/pixmaps.h" + +#include "audacious/main.h" + +#include "audacious/controlsocket.h" +#include "audacious/pluginenum.h" + +#include "audacious/credits.h" +#include "audacious/dnd.h" +#include "audacious/dock.h" +#include "audacious/hints.h" +#include "audacious/input.h" +#include "audacious/prefswin.h" +#include "audacious/skinwin.h" +#include "audacious/genevent.h" +#include "audacious/playback.h" +#include "audacious/playlist.h" +#include "audacious/urldecode.h" +#include "audacious/util.h" +#include "audacious/visualization.h" +#include "libaudacious/configdb.h" + #include "equalizer.h" -#include "hints.h" -#include "input.h" -#include "ui_playlist.h" -#include "prefswin.h" -#include "skinwin.h" -#include "genevent.h" -#include "playback.h" #include "playlist.h" -#include "urldecode.h" -#include "util.h" -#include "visualization.h" -#include "libaudacious/configdb.h" static GTimeVal cb_time; /* click delay for tristate is defined by TRISTATE_THRESHOLD */
--- a/Plugins/UserInterface/wa2gui/mainwin.h Thu Sep 07 19:57:27 2006 -0700 +++ b/Plugins/UserInterface/wa2gui/mainwin.h Thu Sep 07 20:27:46 2006 -0700 @@ -24,7 +24,7 @@ #include <gtk/gtk.h> -#include "widgets/widgetcore.h" +#include "audacious/widgets/widgetcore.h" /* yes, main window size is fixed */ #define MAINWIN_WIDTH (gint)275
--- a/Plugins/UserInterface/wa2gui/playlist.c Thu Sep 07 19:57:27 2006 -0700 +++ b/Plugins/UserInterface/wa2gui/playlist.c Thu Sep 07 20:27:46 2006 -0700 @@ -22,7 +22,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "ui_playlist.h" +#include "playlist.h" +#include "equalizer.h" +#include "mainwin.h" #include <glib.h> #include <glib/gi18n.h> @@ -31,27 +33,25 @@ #include <gtk/gtk.h> #include <string.h> -#include "platform/smartinclude.h" +#include "audacious/platform/smartinclude.h" #include <unistd.h> #include <errno.h> #include "libaudacious/util.h" -#include "dnd.h" -#include "dock.h" -#include "equalizer.h" -#include "hints.h" -#include "input.h" -#include "main.h" -#include "mainwin.h" -#include "playback.h" -#include "playlist.h" -#include "playlist_container.h" -#include "util.h" +#include "audacious/dnd.h" +#include "audacious/dock.h" +#include "audacious/hints.h" +#include "audacious/input.h" +#include "audacious/main.h" +#include "audacious/playback.h" +#include "audacious/playlist.h" +#include "audacious/playlist_container.h" +#include "audacious/util.h" -#include "pixmaps.h" -#include "images/audacious_playlist.xpm" +#include "audacious/pixmaps.h" +#include "audacious/images/audacious_playlist.xpm" #define ITEM_SEPARATOR {"/-", NULL, NULL, 0, "<Separator>", NULL}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/playlist.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,78 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 PLAYLISTWIN_H +#define PLAYLISTWIN_H + +#include <glib.h> + +#include "mainwin.h" +#include "audacious/widgets/widgetcore.h" + +#define PLAYLISTWIN_FRAME_TOP_HEIGHT 20 +#define PLAYLISTWIN_FRAME_BOTTOM_HEIGHT 38 +#define PLAYLISTWIN_FRAME_LEFT_WIDTH 12 +#define PLAYLISTWIN_FRAME_RIGHT_WIDTH 19 + +#define PLAYLISTWIN_MIN_WIDTH MAINWIN_WIDTH +#define PLAYLISTWIN_MIN_HEIGHT MAINWIN_HEIGHT +#define PLAYLISTWIN_WIDTH_SNAP 25 +#define PLAYLISTWIN_HEIGHT_SNAP 29 +#define PLAYLISTWIN_SHADED_HEIGHT MAINWIN_SHADED_HEIGHT +#define PLAYLISTWIN_WIDTH cfg.playlist_width +#define PLAYLISTWIN_HEIGHT \ + (cfg.playlist_shaded ? PLAYLISTWIN_SHADED_HEIGHT : cfg.playlist_height) + +#define PLAYLISTWIN_DEFAULT_WIDTH 275 +#define PLAYLISTWIN_DEFAULT_HEIGHT 232 +#define PLAYLISTWIN_DEFAULT_POS_X 295 +#define PLAYLISTWIN_DEFAULT_POS_Y 20 + +#define PLAYLISTWIN_DEFAULT_FONT "Sans Bold 8" + +gboolean playlistwin_is_shaded(void); +void playlistwin_update_list(void); +gboolean playlistwin_item_visible(gint index); +gint playlistwin_get_toprow(void); +void playlistwin_set_toprow(gint top); +void playlistwin_set_shade_menu_cb(gboolean shaded); +void playlistwin_set_shade(gboolean shaded); +void playlistwin_shade_toggle(void); +void playlistwin_create(void); +void draw_playlist_window(gboolean force); +void playlistwin_hide_timer(void); +void playlistwin_set_time(gint time, gint length, TimerMode mode); +void playlistwin_show(void); +void playlistwin_hide(void); +void playlistwin_set_back_pixmap(void); +void playlistwin_scroll(gint num); +void playlistwin_scroll_up_pushed(void); +void playlistwin_scroll_down_pushed(void); +void playlistwin_select_playlist_to_load(const gchar * default_filename); + +extern GtkWidget *playlistwin; +extern PlayList_List *playlistwin_list; + +extern PButton *playlistwin_shade, *playlistwin_close; + +extern gboolean playlistwin_focus; + +#endif
--- a/Plugins/UserInterface/wa2gui/ui_playlist.h Thu Sep 07 19:57:27 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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 PLAYLISTWIN_H -#define PLAYLISTWIN_H - -#include <glib.h> - -#include "mainwin.h" -#include "widgets/widgetcore.h" - -#define PLAYLISTWIN_FRAME_TOP_HEIGHT 20 -#define PLAYLISTWIN_FRAME_BOTTOM_HEIGHT 38 -#define PLAYLISTWIN_FRAME_LEFT_WIDTH 12 -#define PLAYLISTWIN_FRAME_RIGHT_WIDTH 19 - -#define PLAYLISTWIN_MIN_WIDTH MAINWIN_WIDTH -#define PLAYLISTWIN_MIN_HEIGHT MAINWIN_HEIGHT -#define PLAYLISTWIN_WIDTH_SNAP 25 -#define PLAYLISTWIN_HEIGHT_SNAP 29 -#define PLAYLISTWIN_SHADED_HEIGHT MAINWIN_SHADED_HEIGHT -#define PLAYLISTWIN_WIDTH cfg.playlist_width -#define PLAYLISTWIN_HEIGHT \ - (cfg.playlist_shaded ? PLAYLISTWIN_SHADED_HEIGHT : cfg.playlist_height) - -#define PLAYLISTWIN_DEFAULT_WIDTH 275 -#define PLAYLISTWIN_DEFAULT_HEIGHT 232 -#define PLAYLISTWIN_DEFAULT_POS_X 295 -#define PLAYLISTWIN_DEFAULT_POS_Y 20 - -#define PLAYLISTWIN_DEFAULT_FONT "Sans Bold 8" - -gboolean playlistwin_is_shaded(void); -void playlistwin_update_list(void); -gboolean playlistwin_item_visible(gint index); -gint playlistwin_get_toprow(void); -void playlistwin_set_toprow(gint top); -void playlistwin_set_shade_menu_cb(gboolean shaded); -void playlistwin_set_shade(gboolean shaded); -void playlistwin_shade_toggle(void); -void playlistwin_create(void); -void draw_playlist_window(gboolean force); -void playlistwin_hide_timer(void); -void playlistwin_set_time(gint time, gint length, TimerMode mode); -void playlistwin_show(void); -void playlistwin_hide(void); -void playlistwin_set_back_pixmap(void); -void playlistwin_scroll(gint num); -void playlistwin_scroll_up_pushed(void); -void playlistwin_scroll_down_pushed(void); -void playlistwin_select_playlist_to_load(const gchar * default_filename); - -extern GtkWidget *playlistwin; -extern PlayList_List *playlistwin_list; - -extern PButton *playlistwin_shade, *playlistwin_close; - -extern gboolean playlistwin_focus; - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/Makefile Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,39 @@ +include ../../../../mk/rules.mk +include ../../../../mk/init.mk + +OBJECTIVE_LIBS_NOINST = libwidgets.a + +LDFLAGS += -Wl,-export-dynamic + +CFLAGS += \ + $(GTK_CFLAGS) \ + $(LIBGLADE_CFLAGS) \ + $(BEEP_DEFINES) \ + $(ARCH_DEFINES) \ + -I.. \ + -I../../../.. \ + -I../../.. \ + -I../../../../intl \ + +SOURCES = \ + widget.c \ + sbutton.c \ + pbutton.c \ + tbutton.c \ + textbox.c \ + hslider.c \ + menurow.c \ + monostereo.c \ + vis.c \ + svis.c \ + number.c \ + playstatus.c \ + playlist_list.c \ + playlist_slider.c \ + eq_graph.c \ + eq_slider.c \ + skin.c + +OBJECTS = ${SOURCES:.c=.o} + +include ../../../../mk/objective.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/eq_graph.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,149 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> + +#include "audacious/main.h" +#include "skin.h" + +void +init_spline(gfloat * x, gfloat * y, gint n, gfloat * y2) +{ + gint i, k; + gfloat p, qn, sig, un, *u; + + u = (gfloat *) g_malloc(n * sizeof(gfloat)); + + y2[0] = u[0] = 0.0; + + for (i = 1; i < n - 1; i++) { + sig = ((gfloat) x[i] - x[i - 1]) / ((gfloat) x[i + 1] - x[i - 1]); + p = sig * y2[i - 1] + 2.0; + y2[i] = (sig - 1.0) / p; + u[i] = + (((gfloat) y[i + 1] - y[i]) / (x[i + 1] - x[i])) - + (((gfloat) y[i] - y[i - 1]) / (x[i] - x[i - 1])); + u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p; + } + qn = un = 0.0; + + y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.0); + for (k = n - 2; k >= 0; k--) + y2[k] = y2[k] * y2[k + 1] + u[k]; + g_free(u); +} + +gfloat +eval_spline(gfloat xa[], gfloat ya[], gfloat y2a[], gint n, gfloat x) +{ + gint klo, khi, k; + gfloat h, b, a; + + klo = 0; + khi = n - 1; + while (khi - klo > 1) { + k = (khi + klo) >> 1; + if (xa[k] > x) + khi = k; + else + klo = k; + } + h = xa[khi] - xa[klo]; + a = (xa[khi] - x) / h; + b = (x - xa[klo]) / h; + return (a * ya[klo] + b * ya[khi] + + ((a * a * a - a) * y2a[klo] + + (b * b * b - b) * y2a[khi]) * (h * h) / 6.0); +} + +void +eqgraph_draw(Widget * w) +{ + EqGraph *eg = (EqGraph *) w; + GdkPixmap *obj; + GdkColor col; + guint32 cols[19]; + gint i, y, ymin, ymax, py = 0; + gfloat x[] = { 0, 11, 23, 35, 47, 59, 71, 83, 97, 109 }, yf[10]; + + /* + * This avoids the init_spline() function to be inlined. + * Inlining the function caused troubles when compiling with + * `-O' (at least on FreeBSD). + */ + void (*__init_spline) (gfloat *, gfloat *, gint, gfloat *) = init_spline; + + obj = eg->eg_widget.parent; + skin_draw_pixmap(bmp_active_skin, obj, eg->eg_widget.gc, SKIN_EQMAIN, + 0, 294, eg->eg_widget.x, eg->eg_widget.y, + eg->eg_widget.width, eg->eg_widget.height); + skin_draw_pixmap(bmp_active_skin, obj, eg->eg_widget.gc, SKIN_EQMAIN, + 0, 314, eg->eg_widget.x, + eg->eg_widget.y + 9 + + ((cfg.equalizer_preamp * 9) / 20), + eg->eg_widget.width, 1); + + skin_get_eq_spline_colors(bmp_active_skin, cols); + + __init_spline(x, cfg.equalizer_bands, 10, yf); + for (i = 0; i < 109; i++) { + y = 9 - + (gint) ((eval_spline(x, cfg.equalizer_bands, yf, 10, i) * + 9.0) / 20.0); + if (y < 0) + y = 0; + if (y > 18) + y = 18; + if (!i) + py = y; + if (y < py) { + ymin = y; + ymax = py; + } + else { + ymin = py; + ymax = y; + } + py = y; + for (y = ymin; y <= ymax; y++) { + col.pixel = cols[y]; + gdk_gc_set_foreground(eg->eg_widget.gc, &col); + gdk_draw_point(obj, eg->eg_widget.gc, eg->eg_widget.x + i + 2, + eg->eg_widget.y + y); + } + } +} + +EqGraph * +create_eqgraph(GList ** wlist, GdkPixmap * parent, GdkGC * gc, gint x, gint y) +{ + EqGraph *eg; + + eg = g_new0(EqGraph, 1); + widget_init(&eg->eg_widget, parent, gc, x, y, 113, 19, TRUE); + eg->eg_widget.draw = eqgraph_draw; + + widget_list_add(wlist, WIDGET(eg)); + + return eg; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/eq_graph.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,44 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef EQ_GRAPH_H +#define EQ_GRAPH_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "widget.h" + +#define EQ_GRAPH(x) ((EqGraph *)(x)) +struct _EqGraph { + Widget eg_widget; +}; + +typedef struct _EqGraph EqGraph; + +EqGraph *create_eqgraph(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/eq_slider.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,235 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "equalizer.h" +#include "mainwin.h" +#include "skin.h" + +void +eqslider_set_position(EqSlider * es, + gfloat pos) +{ + es->es_position = 25 - (gint) ((pos * 25.0) / 20.0); + + if (es->es_position < 0) + es->es_position = 0; + + if (es->es_position > 50) + es->es_position = 50; + + if (es->es_position >= 24 && es->es_position <= 26) + es->es_position = 25; + + widget_draw(WIDGET(es)); +} + +gfloat +eqslider_get_position(EqSlider * es) +{ + return 20.0 - (((gfloat) es->es_position * 20.0) / 25.0); +} + +void +eqslider_draw(Widget * w) +{ + EqSlider *es = (EqSlider *) w; + GdkPixmap *obj; + SkinPixmapId src; + gint frame; + + src = SKIN_EQMAIN; + obj = es->es_widget.parent; + + frame = 27 - ((es->es_position * 27) / 50); + if (frame < 14) + skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, + (frame * 15) + 13, 164, es->es_widget.x, + es->es_widget.y, es->es_widget.width, + es->es_widget.height); + else + skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, + ((frame - 14) * 15) + 13, 229, es->es_widget.x, + es->es_widget.y, es->es_widget.width, + es->es_widget.height); + if (es->es_isdragging) + skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, 0, + 176, es->es_widget.x + 1, + es->es_widget.y + es->es_position, 11, 11); + else + skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, 0, + 164, es->es_widget.x + 1, + es->es_widget.y + es->es_position, 11, 11); +} + +void +eqslider_set_mainwin_text(EqSlider * es) +{ + gint band = 0; + const gchar *bandname[11] = { N_("PREAMP"), N_("60HZ"), N_("170HZ"), + N_("310HZ"), N_("600HZ"), N_("1KHZ"), + N_("3KHZ"), N_("6KHZ"), N_("12KHZ"), + N_("14KHZ"), N_("16KHZ") + }; + gchar *tmp; + + if (es->es_widget.x > 21) + band = ((es->es_widget.x - 78) / 18) + 1; + + tmp = + g_strdup_printf("EQ: %s: %+.1f DB", _(bandname[band]), + eqslider_get_position(es)); + mainwin_lock_info_text(tmp); + g_free(tmp); +} + +void +eqslider_button_press_cb(GtkWidget * w, + GdkEventButton * event, + gpointer data) +{ + EqSlider *es = EQ_SLIDER(data); + gint y; + + if (widget_contains(&es->es_widget, event->x, event->y)) { + if (event->button == 1) { + y = event->y - es->es_widget.y; + es->es_isdragging = TRUE; + if (y >= es->es_position && y < es->es_position + 11) + es->es_drag_y = y - es->es_position; + else { + es->es_position = y - 5; + es->es_drag_y = 5; + if (es->es_position < 0) + es->es_position = 0; + if (es->es_position > 50) + es->es_position = 50; + if (es->es_position >= 24 && es->es_position <= 26) + es->es_position = 25; + equalizerwin_eq_changed(); + } + + eqslider_set_mainwin_text(es); + widget_draw(WIDGET(es)); + } + if (event->button == 4) { + es->es_position -= 2; + if (es->es_position < 0) + es->es_position = 0; + equalizerwin_eq_changed(); + widget_draw(WIDGET(es)); + } + } +} + +void +eqslider_mouse_scroll_cb(GtkWidget * w, + GdkEventScroll * event, + gpointer data) +{ + EqSlider *es = EQ_SLIDER(data); + + if (!widget_contains(&es->es_widget, event->x, event->y)) + return; + + if (event->direction == GDK_SCROLL_UP) { + es->es_position -= 2; + + if (es->es_position < 0) + es->es_position = 0; + + equalizerwin_eq_changed(); + widget_draw(WIDGET(es)); + } + else { + es->es_position += 2; + + if (es->es_position > 50) + es->es_position = 50; + + equalizerwin_eq_changed(); + widget_draw(WIDGET(es)); + } +} + +void +eqslider_motion_cb(GtkWidget * w, + GdkEventMotion * event, + gpointer data) +{ + EqSlider *es = EQ_SLIDER(data); + gint y; + + y = event->y - es->es_widget.y; + if (es->es_isdragging) { + es->es_position = y - es->es_drag_y; + if (es->es_position < 0) + es->es_position = 0; + if (es->es_position > 50) + es->es_position = 50; + if (es->es_position >= 24 && es->es_position <= 26) + es->es_position = 25; + equalizerwin_eq_changed(); + eqslider_set_mainwin_text(es); + widget_draw(WIDGET(es)); + } +} + +void +eqslider_button_release_cb(GtkWidget * w, + GdkEventButton * event, + gpointer data) +{ + EqSlider *es = EQ_SLIDER(data); + + if (es->es_isdragging) { + es->es_isdragging = FALSE; + mainwin_release_info_text(); + widget_draw(WIDGET(es)); + } +} + +EqSlider * +create_eqslider(GList ** wlist, + GdkPixmap * parent, + GdkGC * gc, + gint x, gint y) +{ + EqSlider *es; + + es = g_new0(EqSlider, 1); + widget_init(&es->es_widget, parent, gc, x, y, 14, 63, TRUE); + es->es_widget.button_press_cb = eqslider_button_press_cb; + es->es_widget.button_release_cb = eqslider_button_release_cb; + es->es_widget.motion_cb = eqslider_motion_cb; + es->es_widget.draw = eqslider_draw; + es->es_widget.mouse_scroll_cb = eqslider_mouse_scroll_cb; + + widget_list_add(wlist, WIDGET(es)); + + return es; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/eq_slider.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,49 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef EQ_SLIDER_H +#define EQ_SLIDER_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "widget.h" + +#define EQ_SLIDER(x) ((EqSlider *)(x)) +struct _EqSlider { + Widget es_widget; + gint es_position; + gboolean es_isdragging; + gint es_drag_y; +}; + +typedef struct _EqSlider EqSlider; + +EqSlider *create_eqslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y); +void eqslider_set_position(EqSlider * es, gfloat pos); +gfloat eqslider_get_position(EqSlider * es); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/hslider.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,203 @@ +/* XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> +#include <gtk/gtk.h> + +#include "skin.h" + +void +hslider_set_position(HSlider * hs, + gint pos) +{ + if (pos == hs->hs_position || hs->hs_pressed) + return; + + hs->hs_position = pos; + + if (hs->hs_frame_cb) + hs->hs_frame = hs->hs_frame_cb(hs->hs_position); + + widget_draw(WIDGET(hs)); +} + +gint +hslider_get_position(HSlider * hs) +{ + return hs->hs_position; +} + +void +hslider_draw(Widget * w) +{ + HSlider *hs = (HSlider *) w; + GdkPixmap *obj; + + obj = hs->hs_widget.parent; + + skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc, + hs->hs_skin_index, hs->hs_frame_offset, + hs->hs_frame * hs->hs_frame_height, hs->hs_widget.x, + hs->hs_widget.y, hs->hs_widget.width, + hs->hs_widget.height); + if (hs->hs_pressed) + skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc, + hs->hs_skin_index, hs->hs_knob_px, + hs->hs_knob_py, hs->hs_widget.x + hs->hs_position, + hs->hs_widget.y + + ((hs->hs_widget.height - hs->hs_knob_height) / 2), + hs->hs_knob_width, hs->hs_knob_height); + else + skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc, + hs->hs_skin_index, hs->hs_knob_nx, hs->hs_knob_ny, + hs->hs_widget.x + hs->hs_position, + hs->hs_widget.y + + ((hs->hs_widget.height - hs->hs_knob_height) / 2), + hs->hs_knob_width, hs->hs_knob_height); +} + +void +hslider_button_press_cb(GtkWidget * w, + GdkEventButton * event, + gpointer data) +{ + HSlider *hs = HSLIDER(data); + gint x; + + if (event->button != 1) + return; + + if (widget_contains(&hs->hs_widget, event->x, event->y)) { + x = event->x - hs->hs_widget.x; + hs->hs_pressed = TRUE; + + if (x >= hs->hs_position && x < hs->hs_position + hs->hs_knob_width) + hs->hs_pressed_x = x - hs->hs_position; + else { + hs->hs_position = x - (hs->hs_knob_width / 2); + hs->hs_pressed_x = hs->hs_knob_width / 2; + if (hs->hs_position < hs->hs_min) + hs->hs_position = hs->hs_min; + if (hs->hs_position > hs->hs_max) + hs->hs_position = hs->hs_max; + if (hs->hs_frame_cb) + hs->hs_frame = hs->hs_frame_cb(hs->hs_position); + + } + + if (hs->hs_motion_cb) + hs->hs_motion_cb(hs->hs_position); + + widget_draw(WIDGET(hs)); + } +} + +void +hslider_motion_cb(GtkWidget * w, GdkEventMotion * event, gpointer data) +{ + HSlider *hs = (HSlider *) data; + gint x; + + if (hs->hs_pressed) { + if (!hs->hs_widget.visible) { + hs->hs_pressed = FALSE; + return; + } + + x = event->x - hs->hs_widget.x; + hs->hs_position = x - hs->hs_pressed_x; + + if (hs->hs_position < hs->hs_min) + hs->hs_position = hs->hs_min; + + if (hs->hs_position > hs->hs_max) + hs->hs_position = hs->hs_max; + + if (hs->hs_frame_cb) + hs->hs_frame = hs->hs_frame_cb(hs->hs_position); + + if (hs->hs_motion_cb) + hs->hs_motion_cb(hs->hs_position); + + widget_draw(WIDGET(hs)); + } +} + +void +hslider_button_release_cb(GtkWidget * w, + GdkEventButton * event, + gpointer data) +{ + HSlider *hs = HSLIDER(data); + + if (hs->hs_pressed) { + hs->hs_pressed = FALSE; + + if (hs->hs_release_cb) + hs->hs_release_cb(hs->hs_position); + + widget_draw(WIDGET(hs)); + } +} + +HSlider * +create_hslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint knx, gint kny, + gint kpx, gint kpy, gint kw, gint kh, gint fh, + gint fo, gint min, gint max, gint(*fcb) (gint), + void (*mcb) (gint), void (*rcb) (gint), SkinPixmapId si) +{ + HSlider *hs; + + hs = g_new0(HSlider, 1); + widget_init(&hs->hs_widget, parent, gc, x, y, w, h, 1); + hs->hs_widget.button_press_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + hslider_button_press_cb; + hs->hs_widget.button_release_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + hslider_button_release_cb; + hs->hs_widget.motion_cb = + (void (*)(GtkWidget *, GdkEventMotion *, gpointer)) + hslider_motion_cb; + hs->hs_widget.draw = hslider_draw; + hs->hs_knob_nx = knx; + hs->hs_knob_ny = kny; + hs->hs_knob_px = kpx; + hs->hs_knob_py = kpy; + hs->hs_knob_width = kw; + hs->hs_knob_height = kh; + hs->hs_frame_height = fh; + hs->hs_frame_offset = fo; + hs->hs_min = min; + hs->hs_position = min; + hs->hs_max = max; + hs->hs_frame_cb = fcb; + hs->hs_motion_cb = mcb; + hs->hs_release_cb = rcb; + if (hs->hs_frame_cb) + hs->hs_frame = hs->hs_frame_cb(0); + hs->hs_skin_index = si; + + widget_list_add(wlist, WIDGET(hs)); + + return hs; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/hslider.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,59 @@ +/* XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef HSLIDER_H +#define HSLIDER_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "skin.h" +#include "widget.h" + +#define HSLIDER(x) ((HSlider *)(x)) +struct _HSlider { + Widget hs_widget; + gint hs_frame, hs_frame_offset, hs_frame_height, hs_min, hs_max; + gint hs_knob_nx, hs_knob_ny, hs_knob_px, hs_knob_py; + gint hs_knob_width, hs_knob_height; + gint hs_position; + gboolean hs_pressed; + gint hs_pressed_x, hs_pressed_y; + gint(*hs_frame_cb) (gint); + void (*hs_motion_cb) (gint); + void (*hs_release_cb) (gint); + SkinPixmapId hs_skin_index; +}; + +typedef struct _HSlider HSlider; + +HSlider *create_hslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint knx, gint kny, + gint kpx, gint kpy, gint kw, gint kh, gint fh, + gint fo, gint min, gint max, gint(*fcb) (gint), + void (*mcb) (gint), void (*rcb) (gint), + SkinPixmapId si); + +void hslider_set_position(HSlider * hs, gint pos); +gint hslider_get_position(HSlider * hs); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/menurow.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,186 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> + +#include "audacious/main.h" +#include "menurow.h" +#include "widget.h" + +void +menurow_draw(Widget * widget) +{ + MenuRow *mr = MENU_ROW(widget); + + GdkPixmap *obj = mr->mr_widget.parent; + + if (mr->mr_selected == MENUROW_NONE) { + if (cfg.always_show_cb || mr->mr_bpushed) + skin_draw_pixmap(bmp_active_skin, obj, + mr->mr_widget.gc, + mr->mr_skin_index, + mr->mr_nx, mr->mr_ny, + mr->mr_widget.x, mr->mr_widget.y, 8, 43); + else + skin_draw_pixmap(bmp_active_skin, obj, + mr->mr_widget.gc, + mr->mr_skin_index, + mr->mr_nx + 8, mr->mr_ny, + mr->mr_widget.x, mr->mr_widget.y, 8, 43); + } + else { + skin_draw_pixmap(bmp_active_skin, obj, + mr->mr_widget.gc, + mr->mr_skin_index, + mr->mr_sx + ((mr->mr_selected - 1) * 8), + mr->mr_sy, mr->mr_widget.x, mr->mr_widget.y, 8, 43); + } + if (cfg.always_show_cb || mr->mr_bpushed) { + if (mr->mr_always_selected) + skin_draw_pixmap(bmp_active_skin, obj, + mr->mr_widget.gc, + mr->mr_skin_index, + mr->mr_sx + 8, mr->mr_sy + 10, + mr->mr_widget.x, mr->mr_widget.y + 10, 8, 8); + if (mr->mr_doublesize_selected) + skin_draw_pixmap(bmp_active_skin, obj, + mr->mr_widget.gc, + mr->mr_skin_index, + mr->mr_sx + 24, mr->mr_sy + 26, + mr->mr_widget.x, mr->mr_widget.y + 26, 8, 8); + } + +} + +MenuRowItem +menurow_find_selected(MenuRow * mr, gint x, gint y) +{ + MenuRowItem ret = MENUROW_NONE; + + x -= mr->mr_widget.x; + y -= mr->mr_widget.y; + if (x > 0 && x < 8) { + if (y >= 0 && y <= 10) + ret = MENUROW_OPTIONS; + if (y >= 10 && y <= 17) + ret = MENUROW_ALWAYS; + if (y >= 18 && y <= 25) + ret = MENUROW_FILEINFOBOX; + if (y >= 26 && y <= 33) + ret = MENUROW_DOUBLESIZE; + if (y >= 34 && y <= 42) + ret = MENUROW_VISUALIZATION; + } + return ret; +} + +void +menurow_button_press(GtkWidget * widget, + GdkEventButton * event, + gpointer data) +{ + MenuRow *mr = MENU_ROW(data); + + if (event->button != 1) + return; + + if (widget_contains(&mr->mr_widget, event->x, event->y)) { + mr->mr_bpushed = TRUE; + mr->mr_selected = menurow_find_selected(mr, event->x, event->y); + + widget_draw(WIDGET(mr)); + + if (mr->mr_change_callback) + mr->mr_change_callback(mr->mr_selected); + } +} + +void +menurow_motion(GtkWidget * widget, + GdkEventMotion * event, + gpointer data) +{ + MenuRow *mr = MENU_ROW(data); + + if (mr->mr_bpushed) { + mr->mr_selected = menurow_find_selected(mr, event->x, event->y); + + widget_draw(WIDGET(mr)); + + if (mr->mr_change_callback) + mr->mr_change_callback(mr->mr_selected); + } +} + +void +menurow_button_release(GtkWidget * widget, + GdkEventButton * event, + gpointer data) +{ + MenuRow *mr = MENU_ROW(data); + + if (mr->mr_bpushed) { + mr->mr_bpushed = FALSE; + + if (mr->mr_selected == MENUROW_ALWAYS) + mr->mr_always_selected = !mr->mr_always_selected; + + if (mr->mr_selected == MENUROW_DOUBLESIZE) + mr->mr_doublesize_selected = !mr->mr_doublesize_selected; + + if ((int)(mr->mr_selected) != -1 && mr->mr_release_callback) + mr->mr_release_callback(mr->mr_selected); + + mr->mr_selected = MENUROW_NONE; + + widget_draw(WIDGET(mr)); + } +} + +MenuRow * +create_menurow(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint nx, gint ny, gint sx, gint sy, + void (*ccb) (MenuRowItem), + void (*rcb) (MenuRowItem), SkinPixmapId si) +{ + MenuRow *mr; + + mr = g_new0(MenuRow, 1); + widget_init(&mr->mr_widget, parent, gc, x, y, 8, 43, 1); + mr->mr_widget.draw = menurow_draw; + mr->mr_widget.button_press_cb = menurow_button_press; + mr->mr_widget.motion_cb = menurow_motion; + mr->mr_widget.button_release_cb = menurow_button_release; + mr->mr_nx = nx; + mr->mr_ny = ny; + mr->mr_sx = sx; + mr->mr_sy = sy; + mr->mr_selected = MENUROW_NONE; + mr->mr_change_callback = ccb; + mr->mr_release_callback = rcb; + mr->mr_skin_index = si; + + widget_list_add(wlist, WIDGET(mr)); + return mr; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/menurow.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,61 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef MENUROW_H +#define MENUROW_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "skin.h" +#include "widget.h" + +typedef enum { + MENUROW_NONE, MENUROW_OPTIONS, MENUROW_ALWAYS, MENUROW_FILEINFOBOX, + MENUROW_DOUBLESIZE, MENUROW_VISUALIZATION +} MenuRowItem; + +#define MENU_ROW(x) ((MenuRow *)(x)) +struct _MenuRow { + Widget mr_widget; + gint mr_nx, mr_ny; + gint mr_sx, mr_sy; + MenuRowItem mr_selected; + gboolean mr_bpushed; + gboolean mr_always_selected; + gboolean mr_doublesize_selected; + void (*mr_change_callback) (MenuRowItem); + void (*mr_release_callback) (MenuRowItem); + SkinPixmapId mr_skin_index; +}; + +typedef struct _MenuRow MenuRow; + +MenuRow *create_menurow(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint nx, gint ny, gint sx, gint sy, + void (*ccb) (MenuRowItem), + void (*rcb) (MenuRowItem), SkinPixmapId si); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/monostereo.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,93 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> + +#include "skin.h" +#include "widget.h" + +void +monostereo_draw(Widget * widget) +{ + MonoStereo *ms = (MonoStereo *) widget; + GdkPixmap *obj; + + obj = ms->ms_widget.parent; + + switch (ms->ms_num_channels) { + case 0: + skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc, + ms->ms_skin_index, 29, 12, + ms->ms_widget.x, ms->ms_widget.y, 27, 12); + skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc, + ms->ms_skin_index, 0, 12, + ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12); + break; + case 1: + skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc, + ms->ms_skin_index, 29, 0, + ms->ms_widget.x, ms->ms_widget.y, 27, 12); + skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc, + ms->ms_skin_index, 0, 12, + ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12); + break; + case 2: + skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc, + ms->ms_skin_index, 29, 12, + ms->ms_widget.x, ms->ms_widget.y, 27, 12); + skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc, + ms->ms_skin_index, 0, 0, + ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12); + break; + } +} + +void +monostereo_set_num_channels(MonoStereo * ms, + gint nch) +{ + if (!ms) + return; + + ms->ms_num_channels = nch; + widget_draw(WIDGET(ms)); +} + +MonoStereo * +create_monostereo(GList ** wlist, + GdkPixmap * parent, + GdkGC * gc, + gint x, gint y, + SkinPixmapId si) +{ + MonoStereo *ms; + + ms = g_new0(MonoStereo, 1); + widget_init(&ms->ms_widget, parent, gc, x, y, 56, 12, 1); + ms->ms_widget.draw = monostereo_draw; + ms->ms_skin_index = si; + + widget_list_add(wlist, WIDGET(ms)); + return ms; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/monostereo.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,48 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef MONOSTEREO_H +#define MONOSTEREO_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "skin.h" +#include "widget.h" + +#define MONO_STEREO(x) ((MonoStereo *)(x)) +struct _MonoStereo { + Widget ms_widget; + gint ms_num_channels; + SkinPixmapId ms_skin_index; +}; + +typedef struct _MonoStereo MonoStereo; + +MonoStereo *create_monostereo(GList ** wlist, GdkPixmap * parent, + GdkGC * gc, gint x, gint y, SkinPixmapId si); +void monostereo_set_num_channels(MonoStereo * ms, gint nch); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/number.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,75 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> + +#include "skin.h" + +void +number_set_number(Number * nu, + gint number) +{ + if (number == nu->nu_number) + return; + + nu->nu_number = number; + widget_draw(WIDGET(nu)); +} + +void +number_draw(Widget * w) +{ + Number *nu = NUMBER(w); + GdkPixmap *obj; + + obj = nu->nu_widget.parent; + + if (nu->nu_number <= 11) + skin_draw_pixmap(bmp_active_skin, obj, nu->nu_widget.gc, + nu->nu_skin_index, nu->nu_number * 9, 0, + nu->nu_widget.x, nu->nu_widget.y, 9, 13); + else + skin_draw_pixmap(bmp_active_skin, obj, nu->nu_widget.gc, + nu->nu_skin_index, 90, 0, nu->nu_widget.x, + nu->nu_widget.y, 9, 13); +} + +Number * +create_number(GList ** wlist, + GdkPixmap * parent, + GdkGC * gc, + gint x, gint y, + SkinPixmapId si) +{ + Number *nu; + + nu = g_new0(Number, 1); + widget_init(&nu->nu_widget, parent, gc, x, y, 9, 13, 1); + nu->nu_widget.draw = number_draw; + nu->nu_number = 10; + nu->nu_skin_index = si; + + widget_list_add(wlist, WIDGET(nu)); + return nu; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/number.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,48 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef NUMBER_H +#define NUMBER_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "widget.h" +#include "skin.h" + +#define NUMBER(x) ((Number *)(x)) +struct _Number { + Widget nu_widget; + gint nu_number; + SkinPixmapId nu_skin_index; +}; + +typedef struct _Number Number; + +void number_set_number(Number * nu, gint number); +Number *create_number(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, SkinPixmapId si); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/pbutton.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,194 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "skin.h" +#include "widget.h" + +void +pbutton_draw(PButton * button) +{ + GdkPixmap *obj; + + if (button->pb_allow_draw) { + obj = button->pb_widget.parent; + + if (button->pb_pressed && button->pb_inside) { + skin_draw_pixmap(bmp_active_skin, obj, + button->pb_widget.gc, + button->pb_skin_index2, button->pb_px, + button->pb_py, button->pb_widget.x, + button->pb_widget.y, + button->pb_widget.width, + button->pb_widget.height); + } + else { + skin_draw_pixmap(bmp_active_skin, obj, + button->pb_widget.gc, + button->pb_skin_index1, + button->pb_nx, button->pb_ny, + button->pb_widget.x, button->pb_widget.y, + button->pb_widget.width, + button->pb_widget.height); + } + } +} + +void +pbutton_button_press_cb(GtkWidget * widget, + GdkEventButton * event, + PButton * button) +{ + if (event->button != 1) + return; + + if (widget_contains(&button->pb_widget, event->x, event->y)) { + button->pb_pressed = 1; + button->pb_inside = 1; + widget_draw(WIDGET(button)); + if (button->pb_push_cb) + button->pb_push_cb(); + } +} + +void +pbutton_button_release_cb(GtkWidget * widget, + GdkEventButton * event, + PButton * button) +{ + if (event->button != 1) + return; + if (button->pb_inside && button->pb_pressed) { + button->pb_inside = 0; + widget_draw(WIDGET(button)); + if (button->pb_release_cb) + button->pb_release_cb(); + } + if (button->pb_pressed) + button->pb_pressed = 0; +} + +void +pbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event, + PButton * button) +{ + gint inside; + + if (!button->pb_pressed) + return; + + inside = widget_contains(&button->pb_widget, event->x, event->y); + + if (inside != button->pb_inside) { + button->pb_inside = inside; + widget_draw(WIDGET(button)); + } +} + +void +pbutton_set_skin_index(PButton * b, SkinPixmapId si) +{ + b->pb_skin_index1 = b->pb_skin_index2 = si; +} + +void +pbutton_set_skin_index1(PButton * b, SkinPixmapId si) +{ + b->pb_skin_index1 = si; +} + +void +pbutton_set_skin_index2(PButton * b, SkinPixmapId si) +{ + b->pb_skin_index2 = si; +} + +void +pbutton_set_button_data(PButton * b, gint nx, gint ny, gint px, gint py) +{ + if (nx > -1) + b->pb_nx = nx; + if (ny > -1) + b->pb_ny = ny; + if (px > -1) + b->pb_px = px; + if (py > -1) + b->pb_py = py; +} + + +PButton * +create_pbutton_ex(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint nx, + gint ny, gint px, gint py, void (*push_cb) (void), + void (*release_cb) (void), + SkinPixmapId si1, SkinPixmapId si2) +{ + PButton *b; + + b = g_new0(PButton, 1); + widget_init(&b->pb_widget, parent, gc, x, y, w, h, 1); + b->pb_widget.button_press_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + pbutton_button_press_cb; + b->pb_widget.button_release_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + pbutton_button_release_cb; + b->pb_widget.motion_cb = + (void (*)(GtkWidget *, GdkEventMotion *, gpointer)) + pbutton_motion_cb; + + b->pb_widget.draw = (void (*)(Widget *)) pbutton_draw; + b->pb_nx = nx; + b->pb_ny = ny; + b->pb_px = px; + b->pb_py = py; + b->pb_push_cb = push_cb; + b->pb_release_cb = release_cb; + b->pb_skin_index1 = si1; + b->pb_skin_index2 = si2; + b->pb_allow_draw = TRUE; + b->pb_inside = 0; + b->pb_pressed = 0; + widget_list_add(wlist, WIDGET(b)); + + return b; +} + +PButton * +create_pbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint nx, gint ny, + gint px, gint py, void (*cb) (void), SkinPixmapId si) +{ + return create_pbutton_ex(wlist, parent, gc, x, y, w, h, nx, ny, px, py, + NULL, cb, si, si); +} + +void +free_pbutton(PButton * b) +{ + g_free(b); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/pbutton.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,64 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef PBUTTON_H +#define PBUTTON_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "widget.h" +#include "skin.h" + +#define PBUTTON(x) ((PButton *)(x)) +struct _PButton { + Widget pb_widget; + gint pb_nx, pb_ny; + gint pb_px, pb_py; + gboolean pb_pressed; + gboolean pb_inside; + gboolean pb_allow_draw; + void (*pb_push_cb) (void); + void (*pb_release_cb) (void); + SkinPixmapId pb_skin_index1, pb_skin_index2; +}; + +typedef struct _PButton PButton; + +PButton *create_pbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint nx, gint ny, + gint px, gint py, void (*push_cb) (void), SkinPixmapId si); +PButton *create_pbutton_ex(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint nx, + gint ny, gint px, gint py, void (*push_cb) (void), + void (*release_cb) (void), SkinPixmapId si1, + SkinPixmapId si2); +void free_pbutton(PButton * b); +void pbutton_set_skin_index(PButton * b, SkinPixmapId si); +void pbutton_set_skin_index1(PButton * b, SkinPixmapId si); +void pbutton_set_skin_index2(PButton * b, SkinPixmapId si); +void pbutton_set_button_data(PButton * b, gint nx, gint ny, gint px, gint py); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/playlist_list.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,966 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2006 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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. + */ + +/* + * A note about Pango and some funky spacey fonts: Weirdly baselined + * fonts, or fonts with weird ascents or descents _will_ display a + * little bit weird in the playlist widget, but the display engine + * won't make it look too bad, just a little deranged. I honestly + * don't think it's worth fixing (around...), it doesn't have to be + * perfectly fitting, just the general look has to be ok, which it + * IMHO is. + * + * A second note: The numbers aren't perfectly aligned, but in the + * end it looks better when using a single Pango layout for each + * number. + */ + +#include "widgetcore.h" + +#include <stdlib.h> +#include <string.h> + +#include "audacious/main.h" +#include "audacious/input.h" +#include "audacious/playback.h" +#include "audacious/playlist.h" +#include "playlist.h" +#include "audacious/util.h" + +#include "audacious/debug.h" + +static PangoFontDescription *playlist_list_font = NULL; +static gint ascent, descent, width_delta_digit_one; +static gboolean has_slant; +static guint padding; + +/* FIXME: the following globals should not be needed. */ +static gint width_approx_letters; +static gint width_colon, width_colon_third; +static gint width_approx_digits, width_approx_digits_half; + +GdkPixmap *rootpix; + +void playlist_list_draw(Widget * w); + +/* Sort of stolen from XChat, but not really, as theres uses Xlib */ +static void +shade_gdkimage_generic (GdkVisual *visual, GdkImage *ximg, int bpl, int w, int h, int rm, int gm, int bm, int bg) +{ + int x, y; + int bgr = (256 - rm) * (bg & visual->red_mask); + int bgg = (256 - gm) * (bg & visual->green_mask); + int bgb = (256 - bm) * (bg & visual->blue_mask); + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + unsigned long pixel = gdk_image_get_pixel (ximg, x, y); + int r, g, b; + + r = rm * (pixel & visual->red_mask) + bgr; + g = gm * (pixel & visual->green_mask) + bgg; + b = bm * (pixel & visual->blue_mask) + bgb; + + gdk_image_put_pixel (ximg, x, y, + ((r >> 8) & visual->red_mask) | + ((g >> 8) & visual->green_mask) | + ((b >> 8) & visual->blue_mask)); + } + } +} + +/* and this is definately mine... -nenolod */ +GdkPixmap * +shade_pixmap(GdkPixmap *in, gint x, gint y, gint x_offset, gint y_offset, gint w, gint h, GdkColor *shade_color) +{ + GdkImage *ximg; + GdkPixmap *p = gdk_pixmap_new(in, w, h, -1); + GdkGC *gc = gdk_gc_new(p); + + gdk_draw_pixmap(p, gc, in, x, y, 0, 0, w, h); + + gdk_error_trap_push(); + + ximg = gdk_drawable_copy_to_image(in, NULL, x, y, 0, 0, w, h); /* copy */ + + gdk_error_trap_pop(); + + if (GDK_IS_IMAGE(ximg)) + { + shade_gdkimage_generic(gdk_drawable_get_visual(GDK_WINDOW(playlistwin->window)), + ximg, ximg->bpl, w, h, 60, 60, 60, shade_color->pixel); + + gdk_draw_image(p, gc, ximg, 0, 0, x, y, w, h); + } + else { + cfg.playlist_transparent = FALSE; + } + + g_object_unref(gc); + + return p; +} + +#ifdef GDK_WINDOWING_X11 + +#include <gdk/gdkx.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +GdkDrawable *get_transparency_pixmap(void) +{ + GdkDrawable *root; + XID *pixmaps; + GdkAtom prop_type; + gint prop_size; + GdkPixmap *pixmap; + gboolean ret; + + root = gdk_get_default_root_window(); + + pixmap = NULL; + pixmaps = NULL; + + gdk_error_trap_push(); + + ret = gdk_property_get(root, gdk_atom_intern("_XROOTPMAP_ID", TRUE), + 0, 0, INT_MAX - 3, + FALSE, + &prop_type, NULL, &prop_size, + (guchar **) &pixmaps); + + gdk_error_trap_pop(); + + if ((ret == TRUE) && (prop_type == GDK_TARGET_PIXMAP) && (prop_size >= sizeof(XID)) && (pixmaps != NULL)) + { + pixmap = gdk_pixmap_foreign_new_for_display(gdk_drawable_get_display(root), + pixmaps[0]); + + if (pixmaps != NULL) + g_free(pixmaps); + } + + return GDK_DRAWABLE(pixmap); +} + +static GdkFilterReturn +root_event_cb (GdkXEvent *xev, GdkEventProperty *event, gpointer data) +{ + static Atom at = None; + XEvent *xevent = (XEvent *)xev; + + if (xevent->type == PropertyNotify) + { + if (at == None) + at = XInternAtom (xevent->xproperty.display, "_XROOTPMAP_ID", True); + + if (at == xevent->xproperty.atom) + { + rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(), + skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG)); + + if (cfg.playlist_transparent) + { + playlistwin_update_list(); + draw_playlist_window(TRUE); + } + } + } + + return GDK_FILTER_CONTINUE; +} + +#else + +GdkPixmap *get_transparency_pixmap(void) +{ + return NULL; +} + +#endif + +static gboolean +playlist_list_auto_drag_down_func(gpointer data) +{ + PlayList_List *pl = data; + + if (pl->pl_auto_drag_down) { + playlist_list_move_down(pl); + pl->pl_first++; + playlistwin_update_list(); + return TRUE; + } + return FALSE; +} + +static gboolean +playlist_list_auto_drag_up_func(gpointer data) +{ + PlayList_List *pl = data; + + if (pl->pl_auto_drag_up) { + playlist_list_move_up(pl); + pl->pl_first--; + playlistwin_update_list(); + return TRUE; + + } + return FALSE; +} + +void +playlist_list_move_up(PlayList_List * pl) +{ + GList *list; + + PLAYLIST_LOCK(); + if ((list = playlist_get()) == NULL) { + PLAYLIST_UNLOCK(); + return; + } + if (PLAYLIST_ENTRY(list->data)->selected) { + /* We are at the top */ + PLAYLIST_UNLOCK(); + return; + } + while (list) { + if (PLAYLIST_ENTRY(list->data)->selected) + glist_moveup(list); + list = g_list_next(list); + } + PLAYLIST_UNLOCK(); + if (pl->pl_prev_selected != -1) + pl->pl_prev_selected--; + if (pl->pl_prev_min != -1) + pl->pl_prev_min--; + if (pl->pl_prev_max != -1) + pl->pl_prev_max--; +} + +void +playlist_list_move_down(PlayList_List * pl) +{ + GList *list; + + PLAYLIST_LOCK(); + + if (!(list = g_list_last(playlist_get()))) { + PLAYLIST_UNLOCK(); + return; + } + + if (PLAYLIST_ENTRY(list->data)->selected) { + /* We are at the bottom */ + PLAYLIST_UNLOCK(); + return; + } + + while (list) { + if (PLAYLIST_ENTRY(list->data)->selected) + glist_movedown(list); + list = g_list_previous(list); + } + + PLAYLIST_UNLOCK(); + + if (pl->pl_prev_selected != -1) + pl->pl_prev_selected++; + if (pl->pl_prev_min != -1) + pl->pl_prev_min++; + if (pl->pl_prev_max != -1) + pl->pl_prev_max++; +} + +static void +playlist_list_button_press_cb(GtkWidget * widget, + GdkEventButton * event, + PlayList_List * pl) +{ + gint nr, y; + + if (event->button == 1 && pl->pl_fheight && + widget_contains(&pl->pl_widget, event->x, event->y)) { + + y = event->y - pl->pl_widget.y; + nr = (y / pl->pl_fheight) + pl->pl_first; + + if (nr >= playlist_get_length()) + nr = playlist_get_length() - 1; + + if (!(event->state & GDK_CONTROL_MASK)) + playlist_select_all(FALSE); + + if (event->state & GDK_SHIFT_MASK && pl->pl_prev_selected != -1) { + playlist_select_range(pl->pl_prev_selected, nr, TRUE); + pl->pl_prev_min = pl->pl_prev_selected; + pl->pl_prev_max = nr; + pl->pl_drag_pos = nr - pl->pl_first; + } + else { + if (playlist_select_invert(nr)) { + if (event->state & GDK_CONTROL_MASK) { + if (pl->pl_prev_min == -1) { + pl->pl_prev_min = pl->pl_prev_selected; + pl->pl_prev_max = pl->pl_prev_selected; + } + if (nr < pl->pl_prev_min) + pl->pl_prev_min = nr; + else if (nr > pl->pl_prev_max) + pl->pl_prev_max = nr; + } + else + pl->pl_prev_min = -1; + pl->pl_prev_selected = nr; + pl->pl_drag_pos = nr - pl->pl_first; + } + } + if (event->type == GDK_2BUTTON_PRESS) { + /* + * Ungrab the pointer to prevent us from + * hanging on to it during the sometimes slow + * bmp_playback_initiate(). + */ + gdk_pointer_ungrab(GDK_CURRENT_TIME); + gdk_flush(); + playlist_set_position(nr); + if (!bmp_playback_get_playing()) + bmp_playback_initiate(); + } + + pl->pl_dragging = TRUE; + playlistwin_update_list(); + } +} + +gint +playlist_list_get_playlist_position(PlayList_List * pl, + gint x, + gint y) +{ + gint iy, length; + gint ret; + + if (!widget_contains(WIDGET(pl), x, y) || !pl->pl_fheight) + return -1; + + if ((length = playlist_get_length()) == 0) + return -1; + iy = y - pl->pl_widget.y; + + ret = (iy / pl->pl_fheight) + pl->pl_first; + + if(ret > length-1) + ret = -1; + + return ret; +} + +static void +playlist_list_motion_cb(GtkWidget * widget, + GdkEventMotion * event, + PlayList_List * pl) +{ + gint nr, y, off, i; + + if (pl->pl_dragging) { + y = event->y - pl->pl_widget.y; + nr = (y / pl->pl_fheight); + if (nr < 0) { + nr = 0; + if (!pl->pl_auto_drag_up) { + pl->pl_auto_drag_up = TRUE; + pl->pl_auto_drag_up_tag = + gtk_timeout_add(100, playlist_list_auto_drag_up_func, pl); + } + } + else if (pl->pl_auto_drag_up) + pl->pl_auto_drag_up = FALSE; + + if (nr >= pl->pl_num_visible) { + nr = pl->pl_num_visible - 1; + if (!pl->pl_auto_drag_down) { + pl->pl_auto_drag_down = TRUE; + pl->pl_auto_drag_down_tag = + gtk_timeout_add(100, playlist_list_auto_drag_down_func, + pl); + } + } + else if (pl->pl_auto_drag_down) + pl->pl_auto_drag_down = FALSE; + + off = nr - pl->pl_drag_pos; + if (off) { + for (i = 0; i < abs(off); i++) { + if (off < 0) + playlist_list_move_up(pl); + else + playlist_list_move_down(pl); + + } + playlistwin_update_list(); + } + pl->pl_drag_pos = nr; + } +} + +static void +playlist_list_button_release_cb(GtkWidget * widget, + GdkEventButton * event, + PlayList_List * pl) +{ + pl->pl_dragging = FALSE; + pl->pl_auto_drag_down = FALSE; + pl->pl_auto_drag_up = FALSE; +} + +static void +playlist_list_draw_string(PlayList_List * pl, + PangoFontDescription * font, + gint line, + gint width, + const gchar * text, + guint ppos) +{ + guint plist_length_int; + + PangoLayout *layout; + + REQUIRE_STATIC_LOCK(playlist); + + if (cfg.show_numbers_in_pl) { + gchar *pos_string = g_strdup_printf(cfg.show_separator_in_pl == TRUE ? "%d" : "%d.", ppos); + plist_length_int = + gint_count_digits(playlist_get_length_nolock()) + !cfg.show_separator_in_pl + 1; /* cf.show_separator_in_pl will be 0 if false */ + + padding = plist_length_int; + padding = ((padding + 1) * width_approx_digits); + + layout = gtk_widget_create_pango_layout(playlistwin, pos_string); + pango_layout_set_font_description(layout, playlist_list_font); + pango_layout_set_width(layout, plist_length_int * 100); + + pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); + gdk_draw_layout(pl->pl_widget.parent, pl->pl_widget.gc, + pl->pl_widget.x + + (width_approx_digits * + (-1 + plist_length_int - strlen(pos_string))) + + (width_approx_digits / 4), + pl->pl_widget.y + (line - 1) * pl->pl_fheight + + ascent + abs(descent), layout); + g_free(pos_string); + g_object_unref(layout); + + if (!cfg.show_separator_in_pl) + padding -= (width_approx_digits * 1.5); + } + else { + padding = 3; + } + + width -= padding; + + layout = gtk_widget_create_pango_layout(playlistwin, text); + + pango_layout_set_font_description(layout, playlist_list_font); + pango_layout_set_width(layout, width * PANGO_SCALE); + pango_layout_set_single_paragraph_mode(layout, TRUE); + pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); + gdk_draw_layout(pl->pl_widget.parent, pl->pl_widget.gc, + pl->pl_widget.x + padding + (width_approx_letters / 4), + pl->pl_widget.y + (line - 1) * pl->pl_fheight + + ascent + abs(descent), layout); + + g_object_unref(layout); +} + +void +playlist_list_draw(Widget * w) +{ + PlayList_List *pl = PLAYLIST_LIST(w); + GList *list; + GdkGC *gc; + GdkPixmap *obj; + PangoLayout *layout; + gchar *title; + gint width, height; + gint i, max_first; + guint padding, padding_dwidth, padding_plength; + guint max_time_len = 0; + gfloat queue_tailpadding = 0; + gint tpadding; + gsize tpadding_dwidth = 0; + gint x, y; + guint tail_width; + guint tail_len; + + gchar tail[100]; + gchar queuepos[255]; + gchar length[40]; + + gchar **frags; + gchar *frag0; + + gint plw_w, plw_h; + + GdkRectangle *playlist_rect; + + gc = pl->pl_widget.gc; + + width = pl->pl_widget.width; + height = pl->pl_widget.height; + + obj = pl->pl_widget.parent; + + gtk_window_get_size(GTK_WINDOW(playlistwin), &plw_w, &plw_h); + + playlist_rect = g_new0(GdkRectangle, 1); + + playlist_rect->x = 0; + playlist_rect->y = 0; + playlist_rect->width = plw_w - 17; + playlist_rect->height = plw_h - 36; + + gdk_gc_set_clip_origin(gc, 31, 58); + gdk_gc_set_clip_rectangle(gc, playlist_rect); + + if (cfg.playlist_transparent == FALSE) + { + gdk_gc_set_foreground(gc, + skin_get_color(bmp_active_skin, + SKIN_PLEDIT_NORMALBG)); + gdk_draw_rectangle(obj, gc, TRUE, pl->pl_widget.x, pl->pl_widget.y, + width, height); + } + else + { + if (!rootpix) + rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(), + skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG)); + gdk_draw_pixmap(obj, gc, rootpix, cfg.playlist_x + pl->pl_widget.x, + cfg.playlist_y + pl->pl_widget.y, pl->pl_widget.x, pl->pl_widget.y, + width, height); + } + + if (!playlist_list_font) { + g_critical("Couldn't open playlist font"); + return; + } + + pl->pl_fheight = (ascent + abs(descent)); + pl->pl_num_visible = height / pl->pl_fheight; + + max_first = playlist_get_length() - pl->pl_num_visible; + max_first = MAX(max_first, 0); + + pl->pl_first = CLAMP(pl->pl_first, 0, max_first); + + PLAYLIST_LOCK(); + list = playlist_get(); + list = g_list_nth(list, pl->pl_first); + + /* It sucks having to run the iteration twice but this is the only + way you can reliably get the maximum width so we can get our + playlist nice and aligned... -- plasmaroo */ + + for (i = pl->pl_first; + list && i < pl->pl_first + pl->pl_num_visible; + list = g_list_next(list), i++) { + PlaylistEntry *entry = list->data; + + if (entry->length != -1) + { + g_snprintf(length, sizeof(length), "%d:%-2.2d", + entry->length / 60000, (entry->length / 1000) % 60); + tpadding_dwidth = MAX(tpadding_dwidth, strlen(length)); + } + } + + /* Reset */ + list = playlist_get(); + list = g_list_nth(list, pl->pl_first); + + for (i = pl->pl_first; + list && i < pl->pl_first + pl->pl_num_visible; + list = g_list_next(list), i++) { + gint pos; + PlaylistEntry *entry = list->data; + + if (entry->selected) { + gdk_gc_set_foreground(gc, + skin_get_color(bmp_active_skin, + SKIN_PLEDIT_SELECTEDBG)); + gdk_draw_rectangle(obj, gc, TRUE, pl->pl_widget.x, + pl->pl_widget.y + + ((i - pl->pl_first) * pl->pl_fheight), + width, pl->pl_fheight); + } + + /* FIXME: entry->title should NEVER be NULL, and there should + NEVER be a need to do a UTF-8 conversion. Playlist title + strings should be kept properly. */ + + if (!entry->title) { + gchar *basename = g_path_get_basename(entry->filename); + title = filename_to_utf8(basename); + g_free(basename); + } + else + title = str_to_utf8(entry->title); + + pos = playlist_get_queue_position(entry); + + tail[0] = 0; + queuepos[0] = 0; + length[0] = 0; + + if (pos != -1) + g_snprintf(queuepos, sizeof(queuepos), "%d", pos + 1); + + if (entry->length != -1) + { + g_snprintf(length, sizeof(length), "%d:%-2.2d", + entry->length / 60000, (entry->length / 1000) % 60); + } + + strncat(tail, length, sizeof(tail)); + tail_len = strlen(tail); + + max_time_len = MAX(max_time_len, tail_len); + + if (pos != -1 && tpadding_dwidth <= 0) + tail_width = width - (width_approx_digits * (strlen(queuepos) + 2.25)); + else if (pos != -1) + tail_width = width - (width_approx_digits * (tpadding_dwidth + strlen(queuepos) + 4)); + else if (tpadding_dwidth > 0) + tail_width = width - (width_approx_digits * (tpadding_dwidth + 2.5)); + else + tail_width = width; + + if (i == playlist_get_position_nolock()) + gdk_gc_set_foreground(gc, + skin_get_color(bmp_active_skin, + SKIN_PLEDIT_CURRENT)); + else + gdk_gc_set_foreground(gc, + skin_get_color(bmp_active_skin, + SKIN_PLEDIT_NORMAL)); + playlist_list_draw_string(pl, playlist_list_font, + i - pl->pl_first, tail_width, title, + i + 1); + + x = pl->pl_widget.x + width - width_approx_digits * 2; + y = pl->pl_widget.y + ((i - pl->pl_first) - + 1) * pl->pl_fheight + ascent; + + frags = NULL; + frag0 = NULL; + + if ((strlen(tail) > 0) && (tail != NULL)) { + frags = g_strsplit(tail, ":", 0); + frag0 = g_strconcat(frags[0], ":", NULL); + + layout = gtk_widget_create_pango_layout(playlistwin, frags[1]); + pango_layout_set_font_description(layout, playlist_list_font); + pango_layout_set_width(layout, tail_len * 100); + pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); + gdk_draw_layout(obj, gc, x - (0.5 * width_approx_digits), + y + abs(descent), layout); + g_object_unref(layout); + + layout = gtk_widget_create_pango_layout(playlistwin, frag0); + pango_layout_set_font_description(layout, playlist_list_font); + pango_layout_set_width(layout, tail_len * 100); + pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); + gdk_draw_layout(obj, gc, x - (0.75 * width_approx_digits), + y + abs(descent), layout); + g_object_unref(layout); + + g_free(frag0); + g_strfreev(frags); + } + + if (pos != -1) { + + /* DON'T remove the commented code yet please -- Milosz */ + + if (tpadding_dwidth > 0) + queue_tailpadding = tpadding_dwidth + 1; + else + queue_tailpadding = -0.75; + + gdk_draw_rectangle(obj, gc, FALSE, + x - + (((queue_tailpadding + + strlen(queuepos)) * + width_approx_digits) + + (width_approx_digits / 4)), + y + abs(descent), + (strlen(queuepos)) * + width_approx_digits + + (width_approx_digits / 2), + pl->pl_fheight - 2); + + layout = + gtk_widget_create_pango_layout(playlistwin, queuepos); + pango_layout_set_font_description(layout, playlist_list_font); + pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); + + gdk_draw_layout(obj, gc, + x - + ((queue_tailpadding + + strlen(queuepos)) * width_approx_digits) + + (width_approx_digits / 4), + y + abs(descent), layout); + g_object_unref(layout); + } + + g_free(title); + } + + + /* + * Drop target hovering over the playlist, so draw some hint where the + * drop will occur. + * + * This is (currently? unfixably?) broken when dragging files from Qt/KDE apps, + * probably due to DnD signaling problems (actually i have no clue). + * + */ + + if (pl->pl_drag_motion) { + guint pos, plength, lpadding; + gint x, y, plx, ply; + + if (cfg.show_numbers_in_pl) { + lpadding = gint_count_digits(playlist_get_length_nolock()) + 1; + lpadding = ((lpadding + 1) * width_approx_digits); + } + else { + lpadding = 3; + }; + + /* We already hold the mutex and have the playlist locked, so call + the non-locking function. */ + plength = playlist_get_length_nolock(); + + x = pl->drag_motion_x; + y = pl->drag_motion_y; + + plx = pl->pl_widget.x; + ply = pl->pl_widget.y; + + if ((x > pl->pl_widget.x) && !(x > pl->pl_widget.width)) { + + if ((y > pl->pl_widget.y) + && !(y > (pl->pl_widget.height + ply))) { + + pos = ((y - ((Widget *) pl)->y) / pl->pl_fheight) + + pl->pl_first; + + if (pos > (plength)) { + pos = plength; + } + + gdk_gc_set_foreground(gc, + skin_get_color(bmp_active_skin, + SKIN_PLEDIT_CURRENT)); + + gdk_draw_line(obj, gc, pl->pl_widget.x, + pl->pl_widget.y + ((pos - pl->pl_first) * pl->pl_fheight), + pl->pl_widget.width + pl->pl_widget.x - 1, + pl->pl_widget.y + + ((pos - pl->pl_first) * pl->pl_fheight)); + } + + } + + /* When dropping on the borders of the playlist, outside the text area, + * files get appended at the end of the list. Show that too. + */ + + if ((y < ply) || (y > pl->pl_widget.height + ply)) { + if ((y >= 0) || (y <= (pl->pl_widget.height + ply))) { + pos = plength; + gdk_gc_set_foreground(gc, + skin_get_color(bmp_active_skin, + SKIN_PLEDIT_CURRENT)); + + gdk_draw_line(obj, gc, pl->pl_widget.x, + pl->pl_widget.y + + ((pos - pl->pl_first) * pl->pl_fheight), + pl->pl_widget.width + pl->pl_widget.x - 1, + pl->pl_widget.y + + ((pos - pl->pl_first) * pl->pl_fheight)); + + } + } + } + + gdk_gc_set_foreground(gc, + skin_get_color(bmp_active_skin, + SKIN_PLEDIT_NORMAL)); + + if (cfg.show_numbers_in_pl) { + + padding_plength = playlist_get_length_nolock(); + + if (padding_plength == 0) { + padding_dwidth = 0; + } + else { + padding_dwidth = gint_count_digits(playlist_get_length_nolock()); + } + + padding = + (padding_dwidth * + width_approx_digits) + width_approx_digits; + + + /* For italic or oblique fonts we add another half of the + * approximate width */ + if (has_slant) + padding += width_approx_digits_half; + + if (cfg.show_separator_in_pl) { + gdk_draw_line(obj, gc, + pl->pl_widget.x + padding, + pl->pl_widget.y, + pl->pl_widget.x + padding, + pl->pl_widget.y + pl->pl_widget.height - 1); + } + } + + if (tpadding_dwidth != 0) + { + tpadding = (tpadding_dwidth * width_approx_digits) + (width_approx_digits * 1.5); + + if (has_slant) + tpadding += width_approx_digits_half; + + if (cfg.show_separator_in_pl) { + gdk_draw_line(obj, gc, + pl->pl_widget.x + pl->pl_widget.width - tpadding, + pl->pl_widget.y, + pl->pl_widget.x + pl->pl_widget.width - tpadding, + pl->pl_widget.y + pl->pl_widget.height - 1); + } + } + + gdk_gc_set_clip_origin(gc, 0, 0); + gdk_gc_set_clip_rectangle(gc, NULL); + + PLAYLIST_UNLOCK(); + + gdk_flush(); + + g_free(playlist_rect); +} + + +PlayList_List * +create_playlist_list(GList ** wlist, + GdkPixmap * parent, + GdkGC * gc, + gint x, gint y, + gint w, gint h) +{ + PlayList_List *pl; + + pl = g_new0(PlayList_List, 1); + widget_init(&pl->pl_widget, parent, gc, x, y, w, h, TRUE); + + pl->pl_widget.button_press_cb = + (WidgetButtonPressFunc) playlist_list_button_press_cb; + pl->pl_widget.button_release_cb = + (WidgetButtonReleaseFunc) playlist_list_button_release_cb; + pl->pl_widget.motion_cb = (WidgetMotionFunc) playlist_list_motion_cb; + pl->pl_widget.draw = playlist_list_draw; + + pl->pl_prev_selected = -1; + pl->pl_prev_min = -1; + pl->pl_prev_max = -1; + + widget_list_add(wlist, WIDGET(pl)); + +#ifdef GDK_WINDOWING_X11 + gdk_window_set_events (gdk_get_default_root_window(), GDK_PROPERTY_CHANGE_MASK); + gdk_window_add_filter (gdk_get_default_root_window(), (GdkFilterFunc)root_event_cb, pl); +#endif + + return pl; +} + +void +playlist_list_set_font(const gchar * font) +{ + + /* Welcome to bad hack central 2k3 */ + + gchar *font_lower; + gint width_temp; + gint width_temp_0; + + playlist_list_font = pango_font_description_from_string(font); + + text_get_extents(font, + "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz ", + &width_approx_letters, NULL, &ascent, &descent); + + width_approx_letters = (width_approx_letters / 53); + + /* Experimental: We don't weigh the 1 into total because it's width is almost always + * very different from the rest + */ + text_get_extents(font, "023456789", &width_approx_digits, NULL, NULL, + NULL); + width_approx_digits = (width_approx_digits / 9); + + /* Precache some often used calculations */ + width_approx_digits_half = width_approx_digits / 2; + + /* FIXME: We assume that any other number is broader than the "1" */ + text_get_extents(font, "1", &width_temp, NULL, NULL, NULL); + text_get_extents(font, "2", &width_temp_0, NULL, NULL, NULL); + + if (abs(width_temp_0 - width_temp) < 2) { + width_delta_digit_one = 0; + } + else { + width_delta_digit_one = ((width_temp_0 - width_temp) / 2) + 2; + } + + text_get_extents(font, ":", &width_colon, NULL, NULL, NULL); + width_colon_third = width_colon / 4; + + font_lower = g_utf8_strdown(font, strlen(font)); + /* This doesn't take any i18n into account, but i think there is none with TTF fonts + * FIXME: This can probably be retrieved trough Pango too + */ + has_slant = g_strstr_len(font_lower, strlen(font_lower), "oblique") + || g_strstr_len(font_lower, strlen(font_lower), "italic"); + + g_free(font_lower); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/playlist_list.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,60 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef PLAYLIST_LIST_H +#define PLAYLIST_LIST_H + +#include <glib.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#include "widget.h" + +#define PLAYLIST_LIST(x) ((PlayList_List *)(x)) +struct _PlayList_List { + Widget pl_widget; + gint pl_first, pl_fheight, pl_prev_selected, pl_prev_min, pl_prev_max; + gint pl_num_visible, pl_drag_pos; + gboolean pl_dragging, pl_auto_drag_down, pl_auto_drag_up; + gint pl_auto_drag_up_tag, pl_auto_drag_down_tag; + gboolean pl_drag_motion; + gint drag_motion_x, drag_motion_y; + gboolean pl_tooltips; +}; + +typedef struct _PlayList_List PlayList_List; + +PlayList_List *create_playlist_list(GList ** wlist, GdkPixmap * parent, + GdkGC * gc, gint x, gint y, gint w, + gint h); +void playlist_list_move_up(PlayList_List * pl); +void playlist_list_move_down(PlayList_List * pl); +int playlist_list_get_playlist_position(PlayList_List * pl, gint x, gint y); +void playlist_list_set_font(const gchar * font); +GdkPixmap *rootpix; +GdkPixmap *shade_pixmap(GdkDrawable *in, gint x, gint y, gint x_offset, gint y_offset, gint w, gint h, GdkColor *shade_color); +GdkDrawable *get_transparency_pixmap(void); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/playlist_slider.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,168 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> + +#include "audacious/playlist.h" +#include "playlist.h" +#include "skin.h" +#include "widget.h" + +void +playlistslider_draw(Widget * w) +{ + PlaylistSlider *ps = (PlaylistSlider *) w; + GdkPixmap *obj; + gint y, skinx; + + g_return_if_fail(ps != NULL); + g_return_if_fail(ps->ps_list != NULL); + + if (playlist_get_length() > ps->ps_list->pl_num_visible) + y = (ps->ps_list->pl_first * (ps->ps_widget.height - 19)) / + (playlist_get_length() - ps->ps_list->pl_num_visible); + else + y = 0; + + obj = ps->ps_widget.parent; + + if (ps->ps_back_image) { + if (skin_get_id() != ps->ps_skin_id) + ps->ps_skin_id = skin_get_id(); + else if (ps->ps_widget.height == ps->ps_prev_height) + gdk_draw_image(obj, ps->ps_widget.gc, + ps->ps_back_image, 0, 0, + ps->ps_widget.x, + ps->ps_widget.y + ps->ps_prev_y, 8, 18); + gdk_image_destroy(ps->ps_back_image); + } + + ps->ps_prev_y = y; + ps->ps_prev_height = ps->ps_widget.height; + ps->ps_back_image = gdk_drawable_get_image(obj, ps->ps_widget.x, + ps->ps_widget.y + y, 8, 18); + if (ps->ps_is_draging) + skinx = 61; + else + skinx = 52; + + skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, SKIN_PLEDIT, + skinx, 53, ps->ps_widget.x, ps->ps_widget.y + y, 8, 18); +} + +static void +playlistslider_set_pos(PlaylistSlider * ps, gint y) +{ + gint pos; + + y = CLAMP(y, 0, ps->ps_widget.height - 19); + + pos = (y * (playlist_get_length() - ps->ps_list->pl_num_visible)) / + (ps->ps_widget.height - 19); + playlistwin_set_toprow(pos); +} + + +void +playlistslider_button_press_cb(GtkWidget * widget, + GdkEventButton * event, PlaylistSlider * ps) +{ + gint y = event->y - ps->ps_widget.y; + + if (!widget_contains(&ps->ps_widget, event->x, event->y)) + return; + + if (event->button != 1 && event->button != 2) + return; + + if ((y >= ps->ps_prev_y && y < ps->ps_prev_y + 18)) { + ps->ps_is_draging |= event->button; + ps->ps_drag_y = y - ps->ps_prev_y; + widget_draw(WIDGET(ps)); + } + else if (event->button == 2) { + playlistslider_set_pos(ps, y); + ps->ps_is_draging |= event->button; + ps->ps_drag_y = 0; + widget_draw(WIDGET(ps)); + } + else { + gint n = ps->ps_list->pl_num_visible / 2; + if (y < ps->ps_prev_y) + n *= -1; + playlistwin_scroll(n); + } +} + +void +playlistslider_button_release_cb(GtkWidget * widget, + GdkEventButton * event, + PlaylistSlider * ps) +{ + if (ps->ps_is_draging) { + ps->ps_is_draging &= ~event->button; + widget_draw(WIDGET(ps)); + } +} + +void +playlistslider_motion_cb(GtkWidget * widget, GdkEventMotion * event, + PlaylistSlider * ps) +{ + gint y; + + if (!ps->ps_is_draging) + return; + + y = event->y - ps->ps_widget.y - ps->ps_drag_y; + playlistslider_set_pos(ps, y); +} + +PlaylistSlider * +create_playlistslider(GList ** wlist, GdkPixmap * parent, + GdkGC * gc, gint x, gint y, gint h, + PlayList_List * list) +{ + PlaylistSlider *ps; + + ps = g_new0(PlaylistSlider, 1); + widget_init(&ps->ps_widget, parent, gc, x, y, 8, h, 1); + + ps->ps_widget.button_press_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + playlistslider_button_press_cb; + + ps->ps_widget.button_release_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + playlistslider_button_release_cb; + + ps->ps_widget.motion_cb = + (void (*)(GtkWidget *, GdkEventMotion *, gpointer)) + playlistslider_motion_cb; + + ps->ps_widget.draw = playlistslider_draw; + ps->ps_list = list; + + widget_list_add(wlist, WIDGET(ps)); + return ps; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/playlist_slider.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,51 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef PLAYLIST_SLIDER_H +#define PLAYLIST_SLIDER_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "playlist_list.h" +#include "widget.h" + +#define PLAYLIST_SLIDER(x) ((PlayerlistSlider *)(x)) +struct _PlaylistSlider { + Widget ps_widget; + PlayList_List *ps_list; + gboolean ps_is_draging; + gint ps_drag_y, ps_prev_y, ps_prev_height; + GdkImage *ps_back_image; + gint ps_skin_id; +}; + +typedef struct _PlaylistSlider PlaylistSlider; + +PlaylistSlider *create_playlistslider(GList ** wlist, GdkPixmap * parent, + GdkGC * gc, gint x, gint y, gint h, + PlayList_List * list); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/playstatus.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,102 @@ +/* XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> + +#include "skin.h" +#include "widget.h" + +void +playstatus_draw(Widget * w) +{ + PlayStatus *ps = PLAY_STATUS(w); + GdkPixmap *obj; + + if (!w) + return; + + obj = ps->ps_widget.parent; + if (ps->ps_status == STATUS_STOP && ps->ps_status_buffering == TRUE) + ps->ps_status_buffering = FALSE; + if (ps->ps_status == STATUS_PLAY && ps->ps_status_buffering == TRUE) + skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, + SKIN_PLAYPAUSE, 39, 0, ps->ps_widget.x, + ps->ps_widget.y, 3, 9); + else if (ps->ps_status == STATUS_PLAY) + skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, + SKIN_PLAYPAUSE, 36, 0, ps->ps_widget.x, + ps->ps_widget.y, 3, 9); + else + skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, + SKIN_PLAYPAUSE, 27, 0, ps->ps_widget.x, + ps->ps_widget.y, 2, 9); + switch (ps->ps_status) { + case STATUS_STOP: + skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, + SKIN_PLAYPAUSE, 18, 0, + ps->ps_widget.x + 2, ps->ps_widget.y, 9, 9); + break; + case STATUS_PAUSE: + skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, + SKIN_PLAYPAUSE, 9, 0, + ps->ps_widget.x + 2, ps->ps_widget.y, 9, 9); + break; + case STATUS_PLAY: + skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, + SKIN_PLAYPAUSE, 1, 0, + ps->ps_widget.x + 3, ps->ps_widget.y, 8, 9); + break; + } +} + +void +playstatus_set_status(PlayStatus * ps, PStatus status) +{ + if (!ps) + return; + + ps->ps_status = status; + widget_draw(WIDGET(ps)); +} + +void +playstatus_set_status_buffering(PlayStatus * ps, gboolean status) +{ + if (!ps) + return; + + ps->ps_status_buffering = status; + widget_draw(WIDGET(ps)); +} + +PlayStatus * +create_playstatus(GList ** wlist, GdkPixmap * parent, + GdkGC * gc, gint x, gint y) +{ + PlayStatus *ps; + + ps = g_new0(PlayStatus, 1); + widget_init(&ps->ps_widget, parent, gc, x, y, 11, 9, TRUE); + ps->ps_widget.draw = playstatus_draw; + + widget_list_add(wlist, WIDGET(ps)); + return ps; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/playstatus.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,46 @@ +/* XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef PLAYSTATUS_H +#define PLAYSTATUS_H + +#include "widget.h" + +typedef enum { + STATUS_STOP, STATUS_PAUSE, STATUS_PLAY +} PStatus; + +#define PLAY_STATUS(x) ((PlayStatus *)(x)) +struct _PlayStatus { + Widget ps_widget; + PStatus ps_status; + gboolean ps_status_buffering; +}; + +typedef struct _PlayStatus PlayStatus; + +void playstatus_set_status(PlayStatus * ps, PStatus status); +void playstatus_set_status_buffering(PlayStatus * ps, gboolean status); +PlayStatus *create_playstatus(GList ** wlist, GdkPixmap * parent, + GdkGC * gc, gint x, gint y); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/sbutton.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,99 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +void +sbutton_button_press_cb(GtkWidget * widget, + GdkEventButton * event, + SButton * button) +{ + if (event->button != 1) + return; + + if (widget_contains(&button->sb_widget, event->x, event->y)) { + button->sb_pressed = 1; + button->sb_inside = 1; + } +} + +void +sbutton_button_release_cb(GtkWidget * widget, GdkEventButton * event, + SButton * button) +{ + if (event->button != 1) + return; + if (button->sb_inside && button->sb_pressed) { + button->sb_inside = 0; + if (button->sb_push_cb) + button->sb_push_cb(); + } + if (button->sb_pressed) + button->sb_pressed = 0; +} + +void +sbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event, + SButton * button) +{ + int inside; + + if (!button->sb_pressed) + return; + + inside = widget_contains(&button->sb_widget, event->x, event->y); + + if (inside != button->sb_inside) + button->sb_inside = inside; +} + +SButton * +create_sbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, void (*cb) (void)) +{ + SButton *b; + + b = g_new0(SButton, 1); + widget_init(&b->sb_widget, parent, gc, x, y, w, h, 1); + b->sb_widget.button_press_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + sbutton_button_press_cb; + b->sb_widget.button_release_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + sbutton_button_release_cb; + b->sb_widget.motion_cb = + (void (*)(GtkWidget *, GdkEventMotion *, gpointer)) + sbutton_motion_cb; + b->sb_push_cb = cb; + + widget_list_add(wlist, WIDGET(b)); + return b; +} + +void +free_sbutton(SButton * b) +{ + g_free(b); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/sbutton.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,47 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef SBUTTON_H +#define SBUTTON_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "widget.h" + +#define SBUTTON(x) ((SButton *)(x)) +struct _SButton { + Widget sb_widget; + gint sb_pressed, sb_inside; + void (*sb_push_cb) (void); +}; + +typedef struct _SButton SButton; + +SButton *create_sbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, void (*cb) (void)); +void free_sbutton(SButton * b); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/skin.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,1256 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 + +/* TODO: enforce default sizes! */ + +#include <glib.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "widgetcore.h" + +#include "mainwin.h" +#include "equalizer.h" +#include "playlist.h" + +#include "audacious/main.h" +#include "audacious/skinwin.h" +#include "audacious/util.h" + +#include "audacious/debug.h" + +#include "audacious/platform/smartinclude.h" + +#define EXTENSION_TARGETS 7 + +static gchar *ext_targets[EXTENSION_TARGETS] = { "bmp", "xpm", "png", "svg", + "gif", "jpg", "jpeg" }; + +struct _SkinPixmapIdMapping { + SkinPixmapId id; + const gchar *name; + const gchar *alt_name; + gint width, height; +}; + +struct _SkinMaskInfo { + gint width, height; + gchar *inistr; +}; + +typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping; +typedef struct _SkinMaskInfo SkinMaskInfo; + + +Skin *bmp_active_skin = NULL; + +static gint skin_current_num; + +static SkinMaskInfo skin_mask_info[] = { + {275, 116, "Normal"}, + {275, 16, "WindowShade"}, + {275, 116, "Equalizer"}, + {275, 16, "EqualizerWS"} +}; + +static SkinPixmapIdMapping skin_pixmap_id_map[] = { + {SKIN_MAIN, "main", NULL, 0, 0}, + {SKIN_CBUTTONS, "cbuttons", NULL, 0, 0}, + {SKIN_SHUFREP, "shufrep", NULL, 0, 0}, + {SKIN_TEXT, "text", NULL, 0, 0}, + {SKIN_TITLEBAR, "titlebar", NULL, 0, 0}, + {SKIN_VOLUME, "volume", NULL, 0, 0}, + {SKIN_BALANCE, "balance", "volume", 0, 0}, + {SKIN_MONOSTEREO, "monoster", NULL, 0, 0}, + {SKIN_PLAYPAUSE, "playpaus", NULL, 0, 0}, + {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0}, + {SKIN_POSBAR, "posbar", NULL, 0, 0}, + {SKIN_EQMAIN, "eqmain", NULL, 0, 0}, + {SKIN_PLEDIT, "pledit", NULL, 0, 0}, + {SKIN_EQ_EX, "eq_ex", NULL, 0, 0} +}; + +static guint skin_pixmap_id_map_size = G_N_ELEMENTS(skin_pixmap_id_map); + +static const guchar skin_default_viscolor[24][3] = { + {9, 34, 53}, + {10, 18, 26}, + {0, 54, 108}, + {0, 58, 116}, + {0, 62, 124}, + {0, 66, 132}, + {0, 70, 140}, + {0, 74, 148}, + {0, 78, 156}, + {0, 82, 164}, + {0, 86, 172}, + {0, 92, 184}, + {0, 98, 196}, + {0, 104, 208}, + {0, 110, 220}, + {0, 116, 232}, + {0, 122, 244}, + {0, 128, 255}, + {0, 128, 255}, + {0, 104, 208}, + {0, 80, 160}, + {0, 56, 112}, + {0, 32, 64}, + {200, 200, 200} +}; + +static GdkBitmap * +skin_create_transparent_mask(const gchar *, + const gchar *, + const gchar *, + GdkWindow *, + gint, gint); + +static void +skin_setup_masks(Skin * skin); + +static void +skin_set_default_vis_color(Skin * skin); + + +void +skin_lock(Skin * skin) +{ + g_mutex_lock(skin->lock); +} + +void +skin_unlock(Skin * skin) +{ + g_mutex_unlock(skin->lock); +} + +gboolean +bmp_active_skin_reload(void) +{ + return bmp_active_skin_load(bmp_active_skin->path); +} + +gboolean +bmp_active_skin_load(const gchar * path) +{ + g_return_val_if_fail(bmp_active_skin != NULL, FALSE); + + memset(&bmp_active_skin->properties, 0, sizeof(SkinProperties)); + + if (!skin_load(bmp_active_skin, path)) + return FALSE; + + skin_setup_masks(bmp_active_skin); + + if (cfg.playlist_transparent) + { + if (rootpix != NULL) + g_object_unref(rootpix); + + rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(), + skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG)); + } + + draw_main_window(TRUE); + draw_playlist_window(TRUE); + draw_equalizer_window(TRUE); + + vis_set_window(mainwin_vis, mainwin->window); + playlistwin_update_list(); + + return TRUE; +} + +void +skin_pixmap_free(SkinPixmap * p) +{ + g_return_if_fail(p != NULL); + g_return_if_fail(p->pixmap != NULL); + + g_object_unref(p->pixmap); + p->pixmap = NULL; +} + +Skin * +skin_new(void) +{ + Skin *skin; + skin = g_new0(Skin, 1); + skin->lock = g_mutex_new(); + return skin; +} + +void +skin_free(Skin * skin) +{ + gint i; + + g_return_if_fail(skin != NULL); + + skin_lock(skin); + + for (i = 0; i < SKIN_PIXMAP_COUNT; i++) + skin_pixmap_free(&skin->pixmaps[i]); + + for (i = 0; i < SKIN_PIXMAP_COUNT; i++) { + if (skin->masks[i]) + g_object_unref(skin->masks[i]); + + skin->masks[i] = NULL; + } + + skin_set_default_vis_color(skin); + skin_unlock(skin); +} + +void +skin_destroy(Skin * skin) +{ + g_return_if_fail(skin != NULL); + skin_free(skin); + g_mutex_free(skin->lock); + g_free(skin); +} + +const SkinPixmapIdMapping * +skin_pixmap_id_lookup(guint id) +{ + guint i; + + for (i = 0; i < skin_pixmap_id_map_size; i++) { + if (id == skin_pixmap_id_map[i].id) { + return &skin_pixmap_id_map[i]; + } + } + + return NULL; +} + +const gchar * +skin_pixmap_id_to_name(SkinPixmapId id) +{ + guint i; + + for (i = 0; i < skin_pixmap_id_map_size; i++) { + if (id == skin_pixmap_id_map[i].id) + return skin_pixmap_id_map[i].name; + } + return NULL; +} + +static void +skin_set_default_vis_color(Skin * skin) +{ + memcpy(skin->vis_color, skin_default_viscolor, + sizeof(skin_default_viscolor)); +} + +/* + * I have rewritten this to take an array of possible targets, + * once we find a matching target we now return, instead of loop + * recursively. This allows for us to support many possible format + * targets for our skinning engine than just the original winamp + * formats. + * + * -- nenolod, 16 January 2006 + */ +gchar * +skin_pixmap_locate(const gchar * dirname, gchar ** basenames) +{ + gchar *filename; + gint i; + + for (i = 0; basenames[i]; i++) + if (!(filename = find_file_recursively(dirname, basenames[i]))) + g_free(filename); + else + return filename; + + /* can't find any targets -- sorry */ + return NULL; +} + +/* FIXME: this function is temporary. It will be removed when the skinning system + uses GdkPixbuf in place of GdkPixmap */ + +static GdkPixmap * +pixmap_new_from_file(const gchar * filename) +{ + GdkPixbuf *pixbuf; + GdkPixmap *pixmap; + gint width, height; + + if (!(pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) + return NULL; + + width = gdk_pixbuf_get_width(pixbuf); + height = gdk_pixbuf_get_height(pixbuf); + + if (!(pixmap = gdk_pixmap_new(mainwin->window, width, height, + gdk_rgb_get_visual()->depth))) { + g_object_unref(pixbuf); + return NULL; + } + + gdk_pixbuf_render_to_drawable(pixbuf, pixmap, mainwin_gc, 0, 0, 0, 0, + width, height, GDK_RGB_DITHER_MAX, 0, 0); + g_object_unref(pixbuf); + + return pixmap; +} + +static gboolean +skin_load_pixmap_id(Skin * skin, SkinPixmapId id, const gchar * path_p) +{ + const gchar *path; + gchar *filename; + gint width, height; + const SkinPixmapIdMapping *pixmap_id_mapping; + GdkPixmap *gpm; + SkinPixmap *pm = NULL; + gchar *basenames[EXTENSION_TARGETS * 2 + 1]; /* alternate basenames */ + gint i, y; + + g_return_val_if_fail(skin != NULL, FALSE); + g_return_val_if_fail(id < SKIN_PIXMAP_COUNT, FALSE); + + pixmap_id_mapping = skin_pixmap_id_lookup(id); + g_return_val_if_fail(pixmap_id_mapping != NULL, FALSE); + + memset(&basenames, 0, sizeof(basenames)); + + for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++) + { + basenames[y] = g_strdup_printf("%s.%s", pixmap_id_mapping->name, + ext_targets[i]); + + if (pixmap_id_mapping->alt_name) + basenames[++y] = g_strdup_printf("%s.%s", + pixmap_id_mapping->alt_name, ext_targets[i]); + } + + path = path_p ? path_p : skin->path; + filename = skin_pixmap_locate(path, basenames); + + for (i = 0; basenames[i] != NULL; i++) + { + g_free(basenames[i]); + basenames[i] = NULL; + } + + if (!(gpm = pixmap_new_from_file(filename))) { + g_warning("loading of %s failed", filename); + g_free(filename); + return FALSE; + } + + g_free(filename); + + gdk_drawable_get_size(GDK_DRAWABLE(gpm), &width, &height); + pm = &skin->pixmaps[id]; + pm->pixmap = gpm; + pm->width = width; + pm->height = height; + pm->current_width = width; + pm->current_height = height; + + return TRUE; +} + +void +skin_mask_create(Skin * skin, + const gchar * path, + gint id, + GdkWindow * window) +{ + skin->masks[id] = + skin_create_transparent_mask(path, "region.txt", + skin_mask_info[id].inistr, window, + skin_mask_info[id].width, + skin_mask_info[id].height); +} + +static void +skin_setup_masks(Skin * skin) +{ + GdkBitmap *mask; + + if (cfg.show_wm_decorations) + return; + + if (cfg.player_visible) { + mask = skin_get_mask(skin, SKIN_MASK_MAIN + cfg.player_shaded); + gtk_widget_shape_combine_mask(mainwin, mask, 0, 0); + } + + mask = skin_get_mask(skin, SKIN_MASK_EQ + cfg.equalizer_shaded); + gtk_widget_shape_combine_mask(equalizerwin, mask, 0, 0); +} + +static GdkBitmap * +create_default_mask(GdkWindow * parent, gint w, gint h) +{ + GdkBitmap *ret; + GdkGC *gc; + GdkColor pattern; + + ret = gdk_pixmap_new(parent, w, h, 1); + gc = gdk_gc_new(ret); + pattern.pixel = 1; + gdk_gc_set_foreground(gc, &pattern); + gdk_draw_rectangle(ret, gc, TRUE, 0, 0, w, h); + gdk_gc_destroy(gc); + + return ret; +} + +static void +skin_query_color(GdkColormap * cm, GdkColor * c) +{ +#ifdef GDK_WINDOWING_X11 + XColor xc = { 0,0,0,0,0,0 }; + + xc.pixel = c->pixel; + XQueryColor(GDK_COLORMAP_XDISPLAY(cm), GDK_COLORMAP_XCOLORMAP(cm), &xc); + c->red = xc.red; + c->green = xc.green; + c->blue = xc.blue; +#else + /* do nothing. see what breaks? */ +#endif +} + +static glong +skin_calc_luminance(GdkColor * c) +{ + return (0.212671 * c->red + 0.715160 * c->green + 0.072169 * c->blue); +} + +static void +skin_get_textcolors(GdkPixmap * text, GdkColor * bgc, GdkColor * fgc) +{ + /* + * Try to extract reasonable background and foreground colors + * from the font pixmap + */ + + GdkImage *gi; + GdkColormap *cm; + gint i; + + g_return_if_fail(text != NULL); + + /* Get the first line of text */ + gi = gdk_drawable_get_image(text, 0, 0, 152, 6); + cm = gdk_window_get_colormap(playlistwin->window); + g_return_if_fail(GDK_IS_WINDOW(playlistwin->window)); + + for (i = 0; i < 6; i++) { + GdkColor c; + gint x; + glong d, max_d; + + /* Get a pixel from the middle of the space character */ + bgc[i].pixel = gdk_image_get_pixel(gi, 151, i); + skin_query_color(cm, &bgc[i]); + + max_d = 0; + for (x = 1; x < 150; x++) { + c.pixel = gdk_image_get_pixel(gi, x, i); + skin_query_color(cm, &c); + + d = labs(skin_calc_luminance(&c) - skin_calc_luminance(&bgc[i])); + if (d > max_d) { + memcpy(&fgc[i], &c, sizeof(GdkColor)); + max_d = d; + } + } + } + gdk_image_destroy(gi); +} + +gboolean +init_skins(const gchar * path) +{ + bmp_active_skin = skin_new(); + + if (!bmp_active_skin_load(path)) { + /* FIXME: Oddly, g_message() causes a crash if path is NULL on + * Solaris (see bug #165) */ + if (path) + g_message("Unable to load skin (%s), trying default...", path); + + /* can't load configured skin, retry with default */ + if (!bmp_active_skin_load(BMP_DEFAULT_SKIN_PATH)) { + g_message("Unable to load default skin (%s)! Giving up.", + BMP_DEFAULT_SKIN_PATH); + return FALSE; + } + } + + if (cfg.random_skin_on_play) + skinlist_update(); + + return TRUE; +} + +/* + * Opens and parses a skin's hints file. + * Hints files are somewhat like "scripts" in Winamp3/5. + * We'll probably add scripts to it next. + */ +void +skin_parse_hints(Skin * skin, gchar *path_p) +{ + gchar *filename, *tmp; + + path_p = path_p ? path_p : skin->path; + + filename = find_file_recursively(path_p, "skin.hints"); + + if (filename == NULL) + return; + +#if 0 + skin->description = read_ini_string(filename, "skin", "skinDescription"); +#endif + + tmp = read_ini_string(filename, "skin", "mainwinOthertext"); + + if (tmp != NULL) + skin->properties.mainwin_othertext = atoi(tmp); +} + +static guint +hex_chars_to_int(gchar hi, gchar lo) +{ + /* + * Converts a value in the range 0x00-0xFF + * to a integer in the range 0-65535 + */ + gchar str[3]; + + str[0] = hi; + str[1] = lo; + str[2] = 0; + + return (CLAMP(strtol(str, NULL, 16), 0, 0xFF) << 8); +} + +GdkColor * +skin_load_color(const gchar * path, const gchar * file, + const gchar * section, const gchar * key, + gchar * default_hex) +{ + gchar *filename, *value; + GdkColor *color = NULL; + + filename = find_file_recursively(path, file); + if (filename || default_hex) { + if (filename) { + value = read_ini_string(filename, section, key); + if (value == NULL) { + value = g_strdup(default_hex); + } + } else { + value = g_strdup(default_hex); + } + if (value) { + gchar *ptr = value; + gint len; + + color = g_new0(GdkColor, 1); + g_strstrip(value); + + if (value[0] == '#') + ptr++; + len = strlen(ptr); + /* + * The handling of incomplete values is done this way + * to maximize winamp compatibility + */ + if (len >= 6) { + color->red = hex_chars_to_int(*ptr, *(ptr + 1)); + ptr += 2; + } + if (len >= 4) { + color->green = hex_chars_to_int(*ptr, *(ptr + 1)); + ptr += 2; + } + if (len >= 2) + color->blue = hex_chars_to_int(*ptr, *(ptr + 1)); + + gdk_color_alloc(gdk_window_get_colormap(playlistwin->window), + color); + g_free(value); + } + if (filename) + g_free(filename); + } + return color; +} + + + +GdkBitmap * +skin_create_transparent_mask(const gchar * path, + const gchar * file, + const gchar * section, + GdkWindow * window, + gint width, + gint height) +{ + GdkBitmap *mask = NULL; + GdkGC *gc = NULL; + GdkColor pattern; + GdkPoint *gpoints; + + gchar *filename = NULL; + gboolean created_mask = FALSE; + GArray *num, *point; + guint i, j; + gint k; + + if (path) + filename = find_file_recursively(path, file); + + /* filename will be null if path wasn't set */ + if (!filename) { + return create_default_mask(window, width, height); + } + + if ((num = read_ini_array(filename, section, "NumPoints")) == NULL) { + g_free(filename); + return NULL; + } + + if ((point = read_ini_array(filename, section, "PointList")) == NULL) { + g_array_free(num, TRUE); + g_free(filename); + return NULL; + } + + mask = gdk_pixmap_new(window, width, height, 1); + gc = gdk_gc_new(mask); + + pattern.pixel = 0; + gdk_gc_set_foreground(gc, &pattern); + gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height); + pattern.pixel = 1; + gdk_gc_set_foreground(gc, &pattern); + + j = 0; + for (i = 0; i < num->len; i++) { + if ((int)(point->len - j) >= (g_array_index(num, gint, i) * 2)) { + created_mask = TRUE; + gpoints = g_new(GdkPoint, g_array_index(num, gint, i)); + for (k = 0; k < g_array_index(num, gint, i); k++) { + gpoints[k].x = g_array_index(point, gint, j + k * 2); + gpoints[k].y = g_array_index(point, gint, j + k * 2 + 1); + } + j += k * 2; + gdk_draw_polygon(mask, gc, TRUE, gpoints, + g_array_index(num, gint, i)); + g_free(gpoints); + } + } + g_array_free(num, TRUE); + g_array_free(point, TRUE); + g_free(filename); + + if (!created_mask) + gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height); + + gdk_gc_destroy(gc); + + return mask; +} + +void +skin_load_viscolor(Skin * skin, const gchar * path, const gchar * basename) +{ + FILE *file; + gint i, c; + gchar line[256], *filename; + GArray *a; + + g_return_if_fail(skin != NULL); + g_return_if_fail(path != NULL); + g_return_if_fail(basename != NULL); + + skin_set_default_vis_color(skin); + + filename = find_file_recursively(path, basename); + if (!filename) + return; + + if (!(file = fopen(filename, "r"))) { + g_free(filename); + return; + } + + g_free(filename); + + for (i = 0; i < 24; i++) { + if (fgets(line, 255, file)) { + a = string_to_garray(line); + if (a->len > 2) { + for (c = 0; c < 3; c++) + skin->vis_color[i][c] = g_array_index(a, gint, c); + } + g_array_free(a, TRUE); + } + else + break; + } + + fclose(file); +} + +#if 0 +static void +skin_numbers_generate_dash(Skin * skin) +{ + GdkGC *gc; + GdkPixmap *pixmap; + SkinPixmap *numbers; + + g_return_if_fail(skin != NULL); + + numbers = &skin->pixmaps[SKIN_NUMBERS]; + if (!numbers->pixmap || numbers->current_width < 99) + return; + + gc = gdk_gc_new(numbers->pixmap); + pixmap = gdk_pixmap_new(mainwin->window, 108, + numbers->current_height, + -1); + + skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 0, 0, 0, 0, 99, 13); + skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 90, 0, 99, 0, 9, 13); + skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 20, 6, 101, 6, 5, 1); + + g_object_unref(numbers->pixmap); + g_object_unref(gc); + + numbers->pixmap = pixmap; + numbers->current_width = 108; +} +#endif + +static void +skin_load_cursor(Skin * skin, const gchar * dirname) +{ + const gchar * basename = "normal.cur"; + gchar * filename = NULL; + GdkPixbuf * cursor_pixbuf = NULL; + GdkPixbufAnimation * cursor_animated = NULL; + GdkCursor * cursor_gdk = NULL; + GError * error = NULL; + + filename = find_file_recursively(dirname, basename); + + if (filename && cfg.custom_cursors) { + cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error); + cursor_pixbuf = gdk_pixbuf_animation_get_static_image(cursor_animated); + cursor_gdk = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), + cursor_pixbuf, 0, 0); + } else { + cursor_gdk = gdk_cursor_new(GDK_LEFT_PTR); + } + + gdk_window_set_cursor(mainwin->window, cursor_gdk); + gdk_window_set_cursor(playlistwin->window, cursor_gdk); + gdk_window_set_cursor(equalizerwin->window, cursor_gdk); + gdk_cursor_unref(cursor_gdk); +} + +static void +skin_load_pixmaps(Skin * skin, const gchar * path) +{ + GdkPixmap *text_pm; + guint i; + + for (i = 0; i < SKIN_PIXMAP_COUNT; i++) + skin_load_pixmap_id(skin, i, path); + + text_pm = skin->pixmaps[SKIN_TEXT].pixmap; + + if (text_pm) + skin_get_textcolors(text_pm, skin->textbg, skin->textfg); + +#if 0 + if (skin->pixmaps[SKIN_NUMBERS].pixmap) + skin_numbers_generate_dash(skin); +#endif + + skin->colors[SKIN_PLEDIT_NORMAL] = + skin_load_color(path, "pledit.txt", "text", "normal", "#2499ff"); + skin->colors[SKIN_PLEDIT_CURRENT] = + skin_load_color(path, "pledit.txt", "text", "current", "#ffeeff"); + skin->colors[SKIN_PLEDIT_NORMALBG] = + skin_load_color(path, "pledit.txt", "text", "normalbg", "#0a120a"); + skin->colors[SKIN_PLEDIT_SELECTEDBG] = + skin_load_color(path, "pledit.txt", "text", "selectedbg", "#0a124a"); + + skin_mask_create(skin, path, SKIN_MASK_MAIN, mainwin->window); + skin_mask_create(skin, path, SKIN_MASK_MAIN_SHADE, mainwin->window); + + skin_mask_create(skin, path, SKIN_MASK_EQ, equalizerwin->window); + skin_mask_create(skin, path, SKIN_MASK_EQ_SHADE, equalizerwin->window); + + skin_load_viscolor(skin, path, "viscolor.txt"); +} + +static gboolean +skin_load_nolock(Skin * skin, const gchar * path, gboolean force) +{ + gchar *cpath; + + g_return_val_if_fail(skin != NULL, FALSE); + g_return_val_if_fail(path != NULL, FALSE); + REQUIRE_LOCK(skin->lock); + + if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR)) + return FALSE; + + if (!force) { + if (skin->path) + if (!strcmp(skin->path, path)) + return FALSE; + } + + skin_current_num++; + + skin->path = g_strdup(path); + + if (!file_is_archive(path)) { + skin_load_pixmaps(skin, path); + skin_load_cursor(skin, path); + + /* Parse the hints for this skin. */ + skin_parse_hints(skin, NULL); + + return TRUE; + } + + if (!(cpath = archive_decompress(path))) { + g_message("Unable to extract skin archive (%s)", path); + return FALSE; + } + + skin_load_pixmaps(skin, cpath); + skin_load_cursor(skin, cpath); + + /* Parse the hints for this skin. */ + skin_parse_hints(skin, cpath); + + del_directory(cpath); + g_free(cpath); + + return TRUE; +} + +void +skin_install_skin(const gchar * path) +{ + gchar *command; + + g_return_if_fail(path != NULL); + + command = g_strdup_printf("cp %s %s", path, bmp_paths[BMP_PATH_USER_SKIN_DIR]); + if (system(command)) { + g_message("Unable to install skin (%s) into user directory (%s)", + path, bmp_paths[BMP_PATH_USER_SKIN_DIR]); + } + g_free(command); +} + + +gboolean +skin_load(Skin * skin, const gchar * path) +{ + gboolean error; + + g_return_val_if_fail(skin != NULL, FALSE); + + if (!path) + return FALSE; + + skin_lock(skin); + error = skin_load_nolock(skin, path, FALSE); + skin_unlock(skin); + + return error; +} + +gboolean +skin_reload_forced(void) +{ + gboolean error; + + skin_lock(bmp_active_skin); + error = skin_load_nolock(bmp_active_skin, bmp_active_skin->path, TRUE); + skin_unlock(bmp_active_skin); + + return error; +} + +void +skin_reload(Skin * skin) +{ + g_return_if_fail(skin != NULL); + skin_load_nolock(skin, skin->path, TRUE); +} + + +static SkinPixmap * +skin_get_pixmap(Skin * skin, SkinPixmapId map_id) +{ + g_return_val_if_fail(skin != NULL, NULL); + g_return_val_if_fail(map_id < SKIN_PIXMAP_COUNT, NULL); + + return &skin->pixmaps[map_id]; +} + +GdkBitmap * +skin_get_mask(Skin * skin, SkinMaskId mi) +{ + g_return_val_if_fail(skin != NULL, NULL); + g_return_val_if_fail(mi < SKIN_PIXMAP_COUNT, NULL); + + return skin->masks[mi]; +} + +GdkColor * +skin_get_color(Skin * skin, SkinColorId color_id) +{ + GdkColor *ret = NULL; + + g_return_val_if_fail(skin != NULL, NULL); + + switch (color_id) { + case SKIN_TEXTBG: + if (skin->pixmaps[SKIN_TEXT].pixmap) + ret = skin->textbg; + else + ret = skin->def_textbg; + break; + case SKIN_TEXTFG: + if (skin->pixmaps[SKIN_TEXT].pixmap) + ret = skin->textfg; + else + ret = skin->def_textfg; + break; + default: + if (color_id < SKIN_COLOR_COUNT) + ret = skin->colors[color_id]; + break; + } + return ret; +} + +void +skin_get_viscolor(Skin * skin, guchar vis_color[24][3]) +{ + gint i; + + g_return_if_fail(skin != NULL); + + for (i = 0; i < 24; i++) { + vis_color[i][0] = skin->vis_color[i][0]; + vis_color[i][1] = skin->vis_color[i][1]; + vis_color[i][2] = skin->vis_color[i][2]; + } +} + +gint +skin_get_id(void) +{ + return skin_current_num; +} + +void +skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc, + SkinPixmapId pixmap_id, + gint xsrc, gint ysrc, gint xdest, gint ydest, + gint width, gint height) +{ + SkinPixmap *pixmap; + + g_return_if_fail(skin != NULL); + + pixmap = skin_get_pixmap(skin, pixmap_id); + g_return_if_fail(pixmap != NULL); + g_return_if_fail(pixmap->pixmap != NULL); + + if (xsrc > pixmap->width || ysrc > pixmap->height) + return; + + width = MIN(width, pixmap->width - xsrc); + height = MIN(height, pixmap->height - ysrc); + gdk_draw_pixmap(drawable, gc, pixmap->pixmap, xsrc, ysrc, + xdest, ydest, width, height); +} + +void +skin_get_eq_spline_colors(Skin * skin, guint32 colors[19]) +{ + gint i; + GdkPixmap *pixmap; + GdkImage *img; + SkinPixmap *eqmainpm; + + g_return_if_fail(skin != NULL); + + eqmainpm = &skin->pixmaps[SKIN_EQMAIN]; + if (eqmainpm->pixmap && + eqmainpm->current_width >= 116 && eqmainpm->current_height >= 313) + pixmap = eqmainpm->pixmap; + else + return; + + if (!GDK_IS_DRAWABLE(pixmap)) + return; + + if (!(img = gdk_drawable_get_image(pixmap, 115, 294, 1, 19))) + return; + + for (i = 0; i < 19; i++) + colors[i] = gdk_image_get_pixel(img, 0, i); + + gdk_image_destroy(img); +} + + +static void +skin_draw_playlistwin_frame_top(Skin * skin, + GdkDrawable * drawable, + GdkGC * gc, + gint width, gint height, gboolean focus) +{ + /* The title bar skin consists of 2 sets of 4 images, 1 set + * for focused state and the other for unfocused. The 4 images + * are: + * + * a. right corner (25,20) + * b. left corner (25,20) + * c. tiler (25,20) + * d. title (100,20) + * + * min allowed width = 100+25+25 = 150 + */ + + gint i, y, c; + + /* get y offset of the pixmap set to use */ + if (focus) + y = 0; + else + y = 21; + + /* left corner */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, y, 0, 0, 25, 20); + + /* titlebar title */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 26, y, + (width - 100) / 2, 0, 100, 20); + + /* titlebar right corner */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 153, y, + width - 25, 0, 25, 20); + + /* tile draw the remaining frame */ + + /* compute tile count */ + c = (width - (100 + 25 + 25)) / 25; + + for (i = 0; i < c / 2; i++) { + /* left of title */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y, + 25 + i * 25, 0, 25, 20); + + /* right of title */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y, + (width + 100) / 2 + i * 25, 0, 25, 20); + } + + if (c & 1) { + /* Odd tile count, so one remaining to draw. Here we split + * it into two and draw half on either side of the title */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y, + ((c / 2) * 25) + 25, 0, 12, 20); + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y, + (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20); + } +} + +static void +skin_draw_playlistwin_frame_bottom(Skin * skin, + GdkDrawable * drawable, + GdkGC * gc, + gint width, gint height, gboolean focus) +{ + /* The bottom frame skin consists of 1 set of 4 images. The 4 + * images are: + * + * a. left corner with menu buttons (125,38) + * b. visualization window (75,38) + * c. right corner with play buttons (150,38) + * d. frame tile (25,38) + * + * (min allowed width = 125+150+25=300 + */ + + gint i, c; + + /* bottom left corner (menu buttons) */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 72, + 0, height - 38, 125, 38); + + c = (width - 275) / 25; + + /* draw visualization window, if width allows */ + if (c >= 3) { + c -= 3; + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 205, 0, + width - (150 + 75), height - 38, 75, 38); + } + + /* Bottom right corner (playbuttons etc) */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, + 126, 72, width - 150, height - 38, 150, 38); + + /* Tile draw the remaining undrawn portions */ + for (i = 0; i < c; i++) + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 179, 0, + 125 + i * 25, height - 38, 25, 38); +} + +static void +skin_draw_playlistwin_frame_sides(Skin * skin, + GdkDrawable * drawable, + GdkGC * gc, + gint width, gint height, gboolean focus) +{ + /* The side frames consist of 2 tile images. 1 for the left, 1 for + * the right. + * a. left (12,29) + * b. right (19,29) + */ + + gint i; + + /* frame sides */ + for (i = 0; i < (height - (20 + 38)) / 29; i++) { + /* left */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 42, + 0, 20 + i * 29, 12, 29); + + /* right */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 32, 42, + width - 19, 20 + i * 29, 19, 29); + } +} + + +void +skin_draw_playlistwin_frame(Skin * skin, + GdkDrawable * drawable, GdkGC * gc, + gint width, gint height, gboolean focus) +{ + skin_draw_playlistwin_frame_top(skin, drawable, gc, width, height, focus); + skin_draw_playlistwin_frame_bottom(skin, drawable, gc, width, height, + focus); + skin_draw_playlistwin_frame_sides(skin, drawable, gc, width, height, + focus); +} + + +void +skin_draw_playlistwin_shaded(Skin * skin, + GdkDrawable * drawable, GdkGC * gc, + gint width, gboolean focus) +{ + /* The shade mode titlebar skin consists of 4 images: + * a) left corner offset (72,42) size (25,14) + * b) right corner, focused offset (99,57) size (50,14) + * c) right corner, unfocused offset (99,42) size (50,14) + * d) bar tile offset (72,57) size (25,14) + */ + + gint i; + + /* left corner */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14); + + /* bar tile */ + for (i = 0; i < (width - 75) / 25; i++) + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 57, + (i * 25) + 25, 0, 25, 14); + + /* right corner */ + skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 99, focus ? 57 : 42, + width - 50, 0, 50, 14); +} + + +void +skin_draw_mainwin_titlebar(Skin * skin, + GdkDrawable * drawable, GdkGC * gc, + gboolean shaded, gboolean focus) +{ + /* The titlebar skin consists of 2 sets of 2 images, one for for + * shaded and the other for unshaded mode, giving a total of 4. + * The images are exactly 275x14 pixels, aligned and arranged + * vertically on each other in the pixmap in the following order: + * + * a) unshaded, focused offset (27, 0) + * b) unshaded, unfocused offset (27, 15) + * c) shaded, focused offset (27, 29) + * d) shaded, unfocused offset (27, 42) + */ + + gint y_offset; + + if (shaded) { + if (focus) + y_offset = 29; + else + y_offset = 42; + } + else { + if (focus) + y_offset = 0; + else + y_offset = 15; + } + + skin_draw_pixmap(skin, drawable, gc, SKIN_TITLEBAR, 27, y_offset, + 0, 0, MAINWIN_WIDTH, MAINWIN_TITLEBAR_HEIGHT); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/skin.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,149 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef SKIN_H +#define SKIN_H + + +#include <glib.h> +#include <gdk/gdk.h> + + +#define BMP_DEFAULT_SKIN_PATH \ + DATA_DIR G_DIR_SEPARATOR_S "Skins" G_DIR_SEPARATOR_S "Default" + + +typedef enum { + SKIN_MAIN = 0, + SKIN_CBUTTONS, + SKIN_TITLEBAR, + SKIN_SHUFREP, + SKIN_TEXT, + SKIN_VOLUME, + SKIN_BALANCE, + SKIN_MONOSTEREO, + SKIN_PLAYPAUSE, + SKIN_NUMBERS, + SKIN_POSBAR, + SKIN_PLEDIT, + SKIN_EQMAIN, + SKIN_EQ_EX, + SKIN_PIXMAP_COUNT +} SkinPixmapId; + +typedef enum { + SKIN_MASK_MAIN = 0, + SKIN_MASK_MAIN_SHADE, + SKIN_MASK_EQ, + SKIN_MASK_EQ_SHADE, + SKIN_MASK_COUNT +} SkinMaskId; + +typedef enum { + SKIN_PLEDIT_NORMAL = 0, + SKIN_PLEDIT_CURRENT, + SKIN_PLEDIT_NORMALBG, + SKIN_PLEDIT_SELECTEDBG, + SKIN_TEXTBG, + SKIN_TEXTFG, + SKIN_COLOR_COUNT +} SkinColorId; + +typedef struct _SkinProperties { + gboolean mainwin_othertext; +} SkinProperties; + +#define SKIN_PIXMAP(x) ((SkinPixmap *)(x)) +typedef struct _SkinPixmap { + GdkPixmap *pixmap; + /* GdkPixmap *def_pixmap; */ + + /* The real size of the pixmap */ + gint width, height; + + /* The size of the pixmap from the current skin, + which might be smaller */ + gint current_width, current_height; +} SkinPixmap; + + +#define SKIN(x) ((Skin *)(x)) +typedef struct _Skin { + GMutex *lock; + gchar *path; + gchar *def_path; + SkinPixmap pixmaps[SKIN_PIXMAP_COUNT]; + GdkColor textbg[6], def_textbg[6]; + GdkColor textfg[6], def_textfg[6]; + GdkColor *colors[SKIN_COLOR_COUNT]; + guchar vis_color[24][3]; + GdkBitmap *masks[SKIN_MASK_COUNT]; + SkinProperties properties; +} Skin; + +extern Skin *bmp_active_skin; + +gboolean init_skins(const gchar * path); +void cleanup_skins(void); + +gboolean bmp_active_skin_load(const gchar * path); +gboolean bmp_active_skin_reload(void); + +Skin *skin_new(void); +gboolean skin_load(Skin * skin, const gchar * path); +void skin_reload(Skin * skin); +void skin_free(Skin * skin); + +GdkBitmap *skin_get_mask(Skin * skin, SkinMaskId mi); +GdkColor *skin_get_color(Skin * skin, SkinColorId color_id); + +void skin_get_viscolor(Skin * skin, guchar vis_color[24][3]); +gint skin_get_id(void); +void skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc, + SkinPixmapId pixmap_id, + gint xsrc, gint ysrc, gint xdest, gint ydest, + gint width, gint height); +void skin_get_eq_spline_colors(Skin * skin, guint32 colors[19]); +void skin_install_skin(const gchar * path); + +void skin_draw_playlistwin_shaded(Skin * skin, + GdkDrawable * drawable, GdkGC * gc, + gint width, gboolean focus); +void skin_draw_playlistwin_frame(Skin * skin, + GdkDrawable * drawable, GdkGC * gc, + gint width, gint height, gboolean focus); + +void skin_draw_mainwin_titlebar(Skin * skin, + GdkDrawable * drawable, GdkGC * gc, + gboolean shaded, gboolean focus); + + +void skin_parse_hints(Skin * skin, gchar *path_p); + + +gboolean +skin_reload_forced(void); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/svis.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,204 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> +#include <string.h> + +#include "audacious/main.h" +#include "mainwin.h" +#include "audacious/plugin.h" +#include "widget.h" +#include "vis.h" + +static gint svis_redraw_delays[] = { 1, 2, 4, 8 }; + +/* FIXME: Are the svis_scope_colors correct? */ +static guint8 svis_scope_colors[] = { 20, 19, 18, 19, 20 }; +static guint8 svis_vu_normal_colors[] = { 17, 17, 17, 12, 12, 12, 2, 2 }; + +#define DRAW_DS_PIXEL(ptr,value) \ + *(ptr) = (value); \ + *((ptr) + 1) = (value); \ + *((ptr) + 76) = (value); \ + *((ptr) + 77) = (value); + +#define SVIS_HEIGHT 5 +#define SVIS_WIDTH 38 + +void +svis_timeout_func(SVis * svis, guchar * data) +{ + static GTimer *timer = NULL; + gulong micros = 9999999; + gboolean falloff = FALSE; + gint i; + + if (!timer) { + timer = g_timer_new(); + g_timer_start(timer); + } + else { + g_timer_elapsed(timer, µs); + if (micros > 14000) + g_timer_reset(timer); + + } + + if (cfg.vis_type == INPUT_VIS_ANALYZER) { + if (micros > 14000) + falloff = TRUE; + + for (i = 0; i < 2; i++) { + if (falloff || data) { + if (data && data[i] > svis->vs_data[i]) + svis->vs_data[i] = data[i]; + else if (falloff) { + if (svis->vs_data[i] >= 2) + svis->vs_data[i] -= 2; + else + svis->vs_data[i] = 0; + } + } + + } + } + else if (data) { + for (i = 0; i < 75; i++) + svis->vs_data[i] = data[i]; + } + + if (micros > 14000) { + if (!svis->vs_refresh_delay) { + svis_draw((Widget *) svis); + svis->vs_refresh_delay = svis_redraw_delays[cfg.vis_refresh]; + + } + svis->vs_refresh_delay--; + } +} + +void +svis_draw(Widget * w) +{ + SVis *svis = (SVis *) w; + gint x, y, h; + guchar svis_color[24][3]; + guchar rgb_data[SVIS_WIDTH * 2 * SVIS_HEIGHT * 2], *ptr, c; + guint32 colors[24]; + GdkRgbCmap *cmap; + + GDK_THREADS_ENTER(); + + skin_get_viscolor(bmp_active_skin, svis_color); + for (y = 0; y < 24; y++) { + colors[y] = + svis_color[y][0] << 16 | svis_color[y][1] << 8 | svis_color[y][2]; + } + cmap = gdk_rgb_cmap_new(colors, 24); + + memset(rgb_data, 0, SVIS_WIDTH * SVIS_HEIGHT); + if (cfg.vis_type == VIS_ANALYZER) { + switch (cfg.vu_mode) { + case VU_NORMAL: + for (y = 0; y < 2; y++) { + ptr = rgb_data + ((y * 3) * 38); + h = (svis->vs_data[y] * 7) / 37; + for (x = 0; x < h; x++, ptr += 5) { + c = svis_vu_normal_colors[x]; + *(ptr) = c; + *(ptr + 1) = c; + *(ptr + 2) = c; + *(ptr + 38) = c; + *(ptr + 39) = c; + *(ptr + 40) = c; + } + } + break; + case VU_SMOOTH: + for (y = 0; y < 2; y++) { + ptr = rgb_data + ((y * 3) * SVIS_WIDTH); + for (x = 0; x < svis->vs_data[y]; x++, ptr++) { + c = 17 - ((x * 15) / 37); + *(ptr) = c; + *(ptr + 38) = c; + } + } + break; + } + } + else if (cfg.vis_type == VIS_SCOPE) { + for (x = 0; x < 38; x++) { + h = svis->vs_data[x << 1] / 3; + ptr = rgb_data + ((4 - h) * 38) + x; + *ptr = svis_scope_colors[h]; + } + } + + gdk_draw_indexed_image(mainwin->window, mainwin_gc, + svis->vs_widget.x, svis->vs_widget.y, + svis->vs_widget.width, + svis->vs_widget.height, + GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data, + 38, cmap); + + gdk_rgb_cmap_free(cmap); + GDK_THREADS_LEAVE(); +} + +void +svis_clear_data(SVis * svis) +{ + gint i; + + if (!svis) + return; + + for (i = 0; i < 75; i++) { + svis->vs_data[i] = (cfg.vis_type == VIS_SCOPE) ? 6 : 0; + } +} + +void +svis_clear(SVis * svis) +{ + gdk_window_clear_area(mainwin->window, svis->vs_widget.x, + svis->vs_widget.y, svis->vs_widget.width, + svis->vs_widget.height); +} + +SVis * +create_svis(GList ** wlist, + GdkPixmap * parent, + GdkGC * gc, + gint x, gint y) +{ + SVis *svis; + + svis = g_new0(SVis, 1); + widget_init(&svis->vs_widget, parent, gc, x, y, SVIS_WIDTH, SVIS_HEIGHT, + 1); + + widget_list_add(wlist, WIDGET(svis)); + return svis; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/svis.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,52 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef SVIS_H +#define SVIS_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "svis.h" +#include "widget.h" + +#define SVIS(x) ((SVis *)(x)) +struct _SVis { + Widget vs_widget; + gint vs_data[75]; + gint vs_refresh_delay; +}; + +typedef struct _SVis SVis; + +void svis_draw(Widget * w); +void svis_timeout_func(SVis * svis, guchar * data); +SVis *create_svis(GList ** wlist, GdkPixmap * parent, GdkGC * gc, gint x, + gint y); +void svis_set_data(SVis * vis, guchar * data); +void svis_clear_data(SVis * vis); +void svis_clear(SVis * vis); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/tbutton.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,176 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> + +#include "widget.h" + +void +tbutton_draw(Widget * w) +{ + TButton *button = TBUTTON(w); + GdkPixmap *obj; + + obj = button->tb_widget.parent; + + if (button->tb_pressed && button->tb_inside) { + if (button->tb_selected) { + skin_draw_pixmap(bmp_active_skin, obj, + button->tb_widget.gc, + button->tb_skin_index, + button->tb_psx, button->tb_psy, + button->tb_widget.x, button->tb_widget.y, + button->tb_widget.width, + button->tb_widget.height); + } + else { + skin_draw_pixmap(bmp_active_skin, obj, + button->tb_widget.gc, + button->tb_skin_index, + button->tb_pux, button->tb_puy, + button->tb_widget.x, button->tb_widget.y, + button->tb_widget.width, + button->tb_widget.height); + } + } + else { + if (button->tb_selected) { + skin_draw_pixmap(bmp_active_skin, obj, + button->tb_widget.gc, + button->tb_skin_index, + button->tb_nsx, button->tb_nsy, + button->tb_widget.x, button->tb_widget.y, + button->tb_widget.width, + button->tb_widget.height); + } + else { + skin_draw_pixmap(bmp_active_skin, obj, + button->tb_widget.gc, + button->tb_skin_index, + button->tb_nux, button->tb_nuy, + button->tb_widget.x, button->tb_widget.y, + button->tb_widget.width, + button->tb_widget.height); + + } + } +} + +void +tbutton_button_press_cb(GtkWidget * widget, GdkEventButton * event, + TButton * button) +{ + if (event->button != 1) + return; + + if (widget_contains(&button->tb_widget, event->x, event->y)) { + button->tb_pressed = 1; + button->tb_inside = 1; + widget_draw(WIDGET(button)); + } +} + +void +tbutton_button_release_cb(GtkWidget * widget, GdkEventButton * event, + TButton * button) +{ + if (event->button != 1) + return; + + if (button->tb_inside && button->tb_pressed) { + button->tb_inside = 0; + button->tb_selected = !button->tb_selected; + + widget_draw(WIDGET(button)); + + if (button->tb_push_cb) + button->tb_push_cb(button->tb_selected); + } + + if (button->tb_pressed) + button->tb_pressed = 0; +} + +void +tbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event, + TButton * button) +{ + gint inside; + + if (!button->tb_pressed) + return; + inside = widget_contains(&button->tb_widget, event->x, event->y); + if (inside != button->tb_inside) { + button->tb_inside = inside; + widget_draw(WIDGET(button)); + } +} + +TButton * +create_tbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint nux, gint nuy, + gint pux, gint puy, gint nsx, gint nsy, gint psx, + gint psy, void (*cb) (gboolean), SkinPixmapId si) +{ + TButton *b; + + b = g_new0(TButton, 1); + widget_init(&b->tb_widget, parent, gc, x, y, w, h, 1); + b->tb_widget.button_press_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + tbutton_button_press_cb; + b->tb_widget.button_release_cb = + (void (*)(GtkWidget *, GdkEventButton *, gpointer)) + tbutton_button_release_cb; + b->tb_widget.motion_cb = + (void (*)(GtkWidget *, GdkEventMotion *, gpointer)) + tbutton_motion_cb; + b->tb_widget.draw = tbutton_draw; + b->tb_nux = nux; + b->tb_nuy = nuy; + b->tb_pux = pux; + b->tb_puy = puy; + b->tb_nsx = nsx; + b->tb_nsy = nsy; + b->tb_psx = psx; + b->tb_psy = psy; + b->tb_push_cb = cb; + b->tb_skin_index = si; + + widget_list_add(wlist, WIDGET(b)); + return b; +} + +void +tbutton_set_toggled(TButton * tb, gboolean toggled) +{ + tb->tb_selected = toggled; + widget_draw(WIDGET(tb)); +} + +void +free_tbutton(TButton * b) +{ + g_free(b); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/tbutton.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,52 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef TBUTTON_H +#define TBUTTON_H + +#include <glib.h> + +#include "skin.h" +#include "widget.h" + +#define TBUTTON(x) ((TButton *)(x)) +struct _TButton { + Widget tb_widget; + gint tb_nux, tb_nuy, tb_pux, tb_puy, tb_nsx, tb_nsy, tb_psx, tb_psy; + gint tb_pressed, tb_inside, tb_selected; + void (*tb_push_cb) (gboolean); + SkinPixmapId tb_skin_index; +}; + +typedef struct _TButton TButton; + +TButton *create_tbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gint h, gint nux, gint nuy, + gint pux, gint puy, gint nsx, gint nsy, gint psx, + gint psy, void (*cb) (gboolean), SkinPixmapId si); +void tbutton_set_toggled(TButton * tb, gboolean toggled); +void free_tbutton(TButton * b); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/textbox.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,579 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <gdk/gdkprivate.h> +#include <string.h> +#include <ctype.h> + +#include "mainwin.h" +#include "audacious/util.h" + +static void textbox_generate_pixmap(TextBox * tb); + +static void +textbox_draw(Widget * w) +{ + TextBox *tb = TEXT_BOX(w); + gint cw; + GdkPixmap *obj; + GdkPixmap *src; + + g_return_if_fail(tb != NULL); + + if (tb->tb_text && + (!tb->tb_pixmap_text || strcmp(tb->tb_text, tb->tb_pixmap_text))) + textbox_generate_pixmap(tb); + + if (tb->tb_pixmap) { + if (skin_get_id() != tb->tb_skin_id) { + tb->tb_skin_id = skin_get_id(); + textbox_generate_pixmap(tb); + } + obj = tb->tb_widget.parent; + src = tb->tb_pixmap; + + cw = tb->tb_pixmap_width - tb->tb_offset; + if (cw > tb->tb_widget.width) + cw = tb->tb_widget.width; + gdk_draw_pixmap(obj, tb->tb_widget.gc, src, tb->tb_offset, 0, + tb->tb_widget.x, tb->tb_widget.y, cw, + tb->tb_widget.height); + if (cw < tb->tb_widget.width) + gdk_draw_pixmap(obj, tb->tb_widget.gc, src, 0, 0, + tb->tb_widget.x + cw, tb->tb_widget.y, + tb->tb_widget.width - cw, tb->tb_widget.height); + } +} + +static gboolean +textbox_scroll(gpointer data) +{ + TextBox *tb = TEXT_BOX(data); + + if (!tb->tb_is_dragging) { + tb->tb_offset += 1; + if (tb->tb_offset >= tb->tb_pixmap_width) + tb->tb_offset -= tb->tb_pixmap_width; + widget_draw(WIDGET(tb)); + } + + return TRUE; +} + +static void +textbox_button_press(GtkWidget * w, GdkEventButton * event, gpointer data) +{ + TextBox *tb = TEXT_BOX(data); + + if (event->button != 1) + return; + if (widget_contains(&tb->tb_widget, event->x, event->y) && + tb->tb_scroll_allowed && + tb->tb_pixmap_width > tb->tb_widget.width && tb->tb_is_scrollable) { + tb->tb_is_dragging = TRUE; + tb->tb_drag_off = tb->tb_offset; + tb->tb_drag_x = event->x; + } +} + +static void +textbox_motion(GtkWidget * w, GdkEventMotion * event, gpointer data) +{ + TextBox *tb = TEXT_BOX(data); + + if (tb->tb_is_dragging) { + if (tb->tb_scroll_allowed && + tb->tb_pixmap_width > tb->tb_widget.width) { + tb->tb_offset = tb->tb_drag_off - (event->x - tb->tb_drag_x); + + while (tb->tb_offset < 0) + tb->tb_offset += tb->tb_pixmap_width; + + while (tb->tb_offset > tb->tb_pixmap_width) + tb->tb_offset -= tb->tb_pixmap_width; + + widget_draw(WIDGET(tb)); + } + } +} + +static void +textbox_button_release(GtkWidget * w, GdkEventButton * event, gpointer data) +{ + TextBox *tb = TEXT_BOX(data); + + if (event->button == 1) + tb->tb_is_dragging = FALSE; +} + +static gboolean +textbox_should_scroll(TextBox * tb) +{ + g_return_val_if_fail(tb != NULL, FALSE); + + if (!tb->tb_scroll_allowed) + return FALSE; + + if (tb->tb_font) { + gint width; + + text_get_extents(tb->tb_fontname, tb->tb_text, &width, NULL, NULL, + NULL); + + if (width <= tb->tb_widget.width) + return FALSE; + else + return TRUE; + } + + if (g_utf8_strlen(tb->tb_text, -1) * 5 > tb->tb_widget.width) + return TRUE; + + return FALSE; +} + +void +textbox_set_text(TextBox * tb, const gchar * text) +{ + g_return_if_fail(tb != NULL); + g_return_if_fail(text != NULL); + + widget_lock(WIDGET(tb)); + + if (tb->tb_text) { + if (!strcmp(text, tb->tb_text)) { + widget_unlock(WIDGET(tb)); + return; + } + g_free(tb->tb_text); + } + + tb->tb_text = str_to_utf8(text); + + widget_unlock(WIDGET(tb)); + widget_draw(WIDGET(tb)); +} + +static void +textbox_generate_xfont_pixmap(TextBox * tb, const gchar * pixmaptext) +{ + gint length, i; + GdkGC *gc, *maskgc; + GdkColor *c, pattern; + GdkBitmap *mask; + PangoLayout *layout; + gint width; + + g_return_if_fail(tb != NULL); + g_return_if_fail(pixmaptext != NULL); + + length = g_utf8_strlen(pixmaptext, -1); + + text_get_extents(tb->tb_fontname, pixmaptext, &width, NULL, NULL, NULL); + + tb->tb_pixmap_width = MAX(width, tb->tb_widget.width); + tb->tb_pixmap = gdk_pixmap_new(mainwin->window, tb->tb_pixmap_width, + tb->tb_widget.height, + gdk_rgb_get_visual()->depth); + gc = tb->tb_widget.gc; + c = skin_get_color(bmp_active_skin, SKIN_TEXTBG); + for (i = 0; i < tb->tb_widget.height; i++) { + gdk_gc_set_foreground(gc, &c[6 * i / tb->tb_widget.height]); + gdk_draw_line(tb->tb_pixmap, gc, 0, i, tb->tb_pixmap_width, i); + } + + mask = gdk_pixmap_new(mainwin->window, tb->tb_pixmap_width, + tb->tb_widget.height, 1); + maskgc = gdk_gc_new(mask); + pattern.pixel = 0; + gdk_gc_set_foreground(maskgc, &pattern); + + gdk_draw_rectangle(mask, maskgc, TRUE, 0, 0, + tb->tb_pixmap_width, tb->tb_widget.height); + pattern.pixel = 1; + gdk_gc_set_foreground(maskgc, &pattern); + + gdk_gc_set_foreground(gc, skin_get_color(bmp_active_skin, SKIN_TEXTFG)); + + layout = gtk_widget_create_pango_layout(mainwin, pixmaptext); + pango_layout_set_font_description(layout, tb->tb_font); + + gdk_draw_layout(tb->tb_pixmap, gc, 0, (tb->tb_font_descent / 2), layout); + g_object_unref(layout); + + g_object_unref(maskgc); + + gdk_gc_set_clip_mask(gc, mask); + c = skin_get_color(bmp_active_skin, SKIN_TEXTFG); + for (i = 0; i < tb->tb_widget.height; i++) { + gdk_gc_set_foreground(gc, &c[6 * i / tb->tb_widget.height]); + gdk_draw_line(tb->tb_pixmap, gc, 0, i, tb->tb_pixmap_width, i); + } + g_object_unref(mask); + gdk_gc_set_clip_mask(gc, NULL); +} + +static void +textbox_handle_special_char(gchar c, gint * x, gint * y) +{ + switch (c) { + case '"': + *x = 130; + *y = 0; + break; + case '\r': + *x = 50; + *y = 6; + break; + case ':': + case ';': + *x = 60; + *y = 6; + break; + case '(': + *x = 65; + *y = 6; + break; + case ')': + *x = 70; + *y = 6; + break; + case '-': + *x = 75; + *y = 6; + break; + case '`': + case '\'': + *x = 80; + *y = 6; + break; + case '!': + *x = 85; + *y = 6; + break; + case '_': + *x = 90; + *y = 6; + break; + case '+': + *x = 95; + *y = 6; + break; + case '\\': + *x = 100; + *y = 6; + break; + case '/': + *x = 105; + *y = 6; + break; + case '[': + *x = 110; + *y = 6; + break; + case ']': + *x = 115; + *y = 6; + break; + case '^': + *x = 120; + *y = 6; + break; + case '&': + *x = 125; + *y = 6; + break; + case '%': + *x = 130; + *y = 6; + break; + case '.': + case ',': + *x = 135; + *y = 6; + break; + case '=': + *x = 140; + *y = 6; + break; + case '$': + *x = 145; + *y = 6; + break; + case '#': + *x = 150; + *y = 6; + break; + case 'å': + case 'Å': + *x = 0; + *y = 12; + break; + case 'ö': + case 'Ö': + *x = 5; + *y = 12; + break; + case 'ä': + case 'Ä': + *x = 10; + *y = 12; + break; + case 'ü': + case 'Ü': + *x = 100; + *y = 0; + break; + case '?': + *x = 15; + *y = 12; + break; + case '*': + *x = 20; + *y = 12; + break; + default: + *x = 145; + *y = 0; + break; + } +} + +static void +textbox_generate_pixmap(TextBox * tb) +{ + gint length, i, x, y, wl; + gchar *pixmaptext; + GdkGC *gc; + + g_return_if_fail(tb != NULL); + + if (tb->tb_pixmap) { + g_object_unref(tb->tb_pixmap); + tb->tb_pixmap = NULL; + } + + /* + * Don't reset the offset if only text after the last '(' has + * changed. This is a hack to avoid visual noice on vbr files + * where we guess the length. + */ + if (!(tb->tb_pixmap_text && strrchr(tb->tb_text, '(') && + !strncmp(tb->tb_pixmap_text, tb->tb_text, + strrchr(tb->tb_text, '(') - tb->tb_text))) + tb->tb_offset = 0; + + g_free(tb->tb_pixmap_text); + tb->tb_pixmap_text = g_strdup(tb->tb_text); + + /* + * wl is the number of (partial) letters visible. Only makes + * sense when using skinned font. + */ + + wl = tb->tb_widget.width / 5; + if (wl * 5 != tb->tb_widget.width) + wl++; + + length = g_utf8_strlen(tb->tb_text, -1); + + tb->tb_is_scrollable = FALSE; + + if (textbox_should_scroll(tb)) { + tb->tb_is_scrollable = TRUE; + pixmaptext = g_strconcat(tb->tb_pixmap_text, " *** ", NULL); + length += 7; + } + else if (!tb->tb_font && length <= wl) { + gint pad = wl - length; + gchar *padchars = g_strnfill(pad, ' '); + + pixmaptext = g_strconcat(tb->tb_pixmap_text, padchars, NULL); + g_free(padchars); + length += pad; + } + else + pixmaptext = g_strdup(tb->tb_pixmap_text); + + + if (tb->tb_is_scrollable) { + if (tb->tb_scroll_enabled && !tb->tb_timeout_tag) { + gint tag; + tag = TEXTBOX_SCROLL_SMOOTH_TIMEOUT; + tb->tb_timeout_tag = gtk_timeout_add(tag, textbox_scroll, tb); + } + } + else { + if (tb->tb_timeout_tag) { + gtk_timeout_remove(tb->tb_timeout_tag); + tb->tb_timeout_tag = 0; + } + tb->tb_offset = 0; + } + + if (tb->tb_font) { + textbox_generate_xfont_pixmap(tb, pixmaptext); + g_free(pixmaptext); + return; + } + + tb->tb_pixmap_width = length * 5; + tb->tb_pixmap = gdk_pixmap_new(mainwin->window, + tb->tb_pixmap_width, 6, + gdk_rgb_get_visual()->depth); + gc = tb->tb_widget.gc; + + for (i = 0; i < length; i++) { + gchar c; + x = y = -1; + c = toupper(pixmaptext[i]); + if (c >= 'A' && c <= 'Z') { + x = 5 * (c - 'A'); + y = 0; + } + else if (c >= '0' && c <= '9') { + x = 5 * (c - '0'); + y = 6; + } + else + textbox_handle_special_char(c, &x, &y); + + skin_draw_pixmap(bmp_active_skin, + tb->tb_pixmap, gc, tb->tb_skin_index, + x, y, i * 5, 0, 5, 6); + } + g_free(pixmaptext); +} + +void +textbox_set_scroll(TextBox * tb, gboolean s) +{ + g_return_if_fail(tb != NULL); + + tb->tb_scroll_enabled = s; + if (tb->tb_scroll_enabled && tb->tb_is_scrollable + && tb->tb_scroll_allowed) { + gint tag; + tag = TEXTBOX_SCROLL_SMOOTH_TIMEOUT; + + if (tb->tb_timeout_tag) + { + gtk_timeout_remove(tb->tb_timeout_tag); + tb->tb_timeout_tag = 0; + } + + tb->tb_timeout_tag = gtk_timeout_add(tag, textbox_scroll, tb); + } + else + { + if (tb->tb_timeout_tag) + { + gtk_timeout_remove(tb->tb_timeout_tag); + tb->tb_timeout_tag = 0; + } + + tb->tb_offset = 0; + widget_draw(WIDGET(tb)); + } + +} + +void +textbox_set_xfont(TextBox * tb, gboolean use_xfont, const gchar * fontname) +{ + gint ascent, descent; + + g_return_if_fail(tb != NULL); + + if (tb->tb_font) { + pango_font_description_free(tb->tb_font); + tb->tb_font = NULL; + } + + tb->tb_widget.y = tb->tb_nominal_y; + tb->tb_widget.height = tb->tb_nominal_height; + + /* Make sure the pixmap is regenerated */ + if (tb->tb_pixmap_text) { + g_free(tb->tb_pixmap_text); + tb->tb_pixmap_text = NULL; + } + + if (!use_xfont || strlen(fontname) == 0) + return; + + tb->tb_font = pango_font_description_from_string(fontname); + tb->tb_fontname = g_strdup(fontname); + + text_get_extents(fontname, + "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz ", + NULL, NULL, &ascent, &descent); + tb->tb_font_ascent = ascent; + tb->tb_font_descent = descent; + + + if (tb->tb_font == NULL) + return; + + tb->tb_widget.height = tb->tb_font_ascent; + if (tb->tb_widget.height > tb->tb_nominal_height) + tb->tb_widget.y -= (tb->tb_widget.height - tb->tb_nominal_height) / 2; + else + tb->tb_widget.height = tb->tb_nominal_height; +} + +TextBox * +create_textbox(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gboolean allow_scroll, SkinPixmapId si) +{ + TextBox *tb; + + tb = g_new0(TextBox, 1); + widget_init(&tb->tb_widget, parent, gc, x, y, w, 6, 1); + tb->tb_widget.button_press_cb = textbox_button_press; + tb->tb_widget.button_release_cb = textbox_button_release; + tb->tb_widget.motion_cb = textbox_motion; + tb->tb_widget.draw = textbox_draw; + tb->tb_scroll_allowed = allow_scroll; + tb->tb_scroll_enabled = TRUE; + tb->tb_skin_index = si; + tb->tb_nominal_y = y; + tb->tb_nominal_height = tb->tb_widget.height; + widget_list_add(wlist, WIDGET(tb)); + tb->tb_timeout_tag = 0; + return tb; +} + +void +textbox_free(TextBox * tb) +{ + g_return_if_fail(tb != NULL); + + if (tb->tb_pixmap) + g_object_unref(tb->tb_pixmap); + g_free(tb->tb_text); + g_free(tb); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/textbox.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,68 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef TEXTBOX_H +#define TEXTBOX_H + +#include <glib.h> +#include <gdk/gdk.h> +#include <pango/pango.h> + +#include "skin.h" +#include "widget.h" + +#define TEXTBOX_SCROLL_TIMEOUT 200 +#define TEXTBOX_SCROLL_SMOOTH_TIMEOUT 30 + +#define TEXT_BOX(x) ((TextBox *)(x)) +struct _TextBox { + Widget tb_widget; + GdkPixmap *tb_pixmap; + gchar *tb_text, *tb_pixmap_text; + gint tb_pixmap_width; + gint tb_offset; + gboolean tb_scroll_allowed, tb_scroll_enabled; + gboolean tb_is_scrollable, tb_is_dragging; + gint tb_timeout_tag, tb_drag_x, tb_drag_off; + gint tb_nominal_y, tb_nominal_height; + gint tb_skin_id; + SkinPixmapId tb_skin_index; + PangoFontDescription *tb_font; + gint tb_font_ascent, tb_font_descent; + gchar *tb_fontname; +}; + +typedef struct _TextBox TextBox; + +void textbox_set_text(TextBox * tb, const gchar * text); +void textbox_set_scroll(TextBox * tb, gboolean s); +TextBox *create_textbox(GList ** wlist, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint w, gboolean allow_scroll, + SkinPixmapId si); +void textbox_set_xfont(TextBox * tb, gboolean use_xfont, + const gchar * fontname); +void textbox_free(TextBox * tb); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/vis.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,291 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> +#include <string.h> + +#include "audacious/main.h" +#include "skin.h" +#include "widget.h" + +static const gfloat vis_afalloff_speeds[] = { 0.34, 0.5, 1.0, 1.3, 1.6 }; +static const gfloat vis_pfalloff_speeds[] = { 1.2, 1.3, 1.4, 1.5, 1.6 }; +static const gint vis_redraw_delays[] = { 1, 2, 4, 8 }; +static const guint8 vis_scope_colors[] = + { 21, 21, 20, 20, 19, 19, 18, 19, 19, 20, 20, 21, 21 }; + +void +vis_timeout_func(Vis * vis, guchar * data) +{ + static GTimer *timer = NULL; + gulong micros = 9999999; + gboolean falloff = FALSE; + gint i; + + if (!timer) { + timer = g_timer_new(); + g_timer_start(timer); + } + else { + g_timer_elapsed(timer, µs); + if (micros > 14000) + g_timer_reset(timer); + + } + + if (cfg.vis_type == VIS_ANALYZER) { + if (micros > 14000) + falloff = TRUE; + if (data || falloff) { + for (i = 0; i < 75; i++) { + if (data && data[i] > vis->vs_data[i]) { + vis->vs_data[i] = data[i]; + if (vis->vs_data[i] > vis->vs_peak[i]) { + vis->vs_peak[i] = vis->vs_data[i]; + vis->vs_peak_speed[i] = 0.01; + + } + else if (vis->vs_peak[i] > 0.0) { + vis->vs_peak[i] -= vis->vs_peak_speed[i]; + vis->vs_peak_speed[i] *= + vis_pfalloff_speeds[cfg.peaks_falloff]; + if (vis->vs_peak[i] < vis->vs_data[i]) + vis->vs_peak[i] = vis->vs_data[i]; + if (vis->vs_peak[i] < 0.0) + vis->vs_peak[i] = 0.0; + } + } + else if (falloff) { + if (vis->vs_data[i] > 0.0) { + vis->vs_data[i] -= + vis_afalloff_speeds[cfg.analyzer_falloff]; + if (vis->vs_data[i] < 0.0) + vis->vs_data[i] = 0.0; + } + if (vis->vs_peak[i] > 0.0) { + vis->vs_peak[i] -= vis->vs_peak_speed[i]; + vis->vs_peak_speed[i] *= + vis_pfalloff_speeds[cfg.peaks_falloff]; + if (vis->vs_peak[i] < vis->vs_data[i]) + vis->vs_peak[i] = vis->vs_data[i]; + if (vis->vs_peak[i] < 0.0) + vis->vs_peak[i] = 0.0; + } + } + } + } + } + else if (data) { + for (i = 0; i < 75; i++) + vis->vs_data[i] = data[i]; + } + + if (micros > 14000) { + if (!vis->vs_refresh_delay) { + vis_draw((Widget *) vis); + vis->vs_refresh_delay = vis_redraw_delays[cfg.vis_refresh]; + + } + vis->vs_refresh_delay--; + } +} + +void +vis_draw(Widget * w) +{ + Vis *vis = (Vis *) w; + gint x, y, h = 0, h2; + guchar vis_color[24][3]; + guchar rgb_data[152 * 32], *ptr, c; + guint32 colors[24]; + GdkRgbCmap *cmap; + + if (!vis->vs_widget.visible) + return; + + skin_get_viscolor(bmp_active_skin, vis_color); + for (y = 0; y < 24; y++) { + colors[y] = + vis_color[y][0] << 16 | vis_color[y][1] << 8 | vis_color[y][2]; + } + cmap = gdk_rgb_cmap_new(colors, 24); + + memset(rgb_data, 0, 76 * 16); + for (y = 1; y < 16; y += 2) { + ptr = rgb_data + (y * 76); + for (x = 0; x < 76; x += 2, ptr += 2) + *ptr = 1; + } + if (cfg.vis_type == VIS_ANALYZER) { + for (x = 0; x < 75; x++) { + if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0) + h = vis->vs_data[x >> 2]; + else if (cfg.analyzer_type == ANALYZER_LINES) + h = vis->vs_data[x]; + if (h && (cfg.analyzer_type == ANALYZER_LINES || + (x % 4) != 3)) { + ptr = rgb_data + ((16 - h) * 76) + x; + switch (cfg.analyzer_mode) { + case ANALYZER_NORMAL: + for (y = 0; y < h; y++, ptr += 76) + *ptr = 18 - h + y; + break; + case ANALYZER_FIRE: + for (y = 0; y < h; y++, ptr += 76) + *ptr = y + 2; + break; + case ANALYZER_VLINES: + for (y = 0; y < h; y++, ptr += 76) + *ptr = 18 - h; + break; + } + } + } + if (cfg.analyzer_peaks) { + for (x = 0; x < 75; x++) { + if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0) + h = vis->vs_peak[x >> 2]; + else if (cfg.analyzer_type == ANALYZER_LINES) + h = vis->vs_peak[x]; + if (h + && (cfg.analyzer_type == ANALYZER_LINES + || (x % 4) != 3)) + rgb_data[(16 - h) * 76 + x] = 23; + } + } + } + else if (cfg.vis_type == VIS_SCOPE) { + for (x = 0; x < 75; x++) { + switch (cfg.scope_mode) { + case SCOPE_DOT: + h = vis->vs_data[x]; + ptr = rgb_data + ((15 - h) * 76) + x; + *ptr = vis_scope_colors[h]; + break; + case SCOPE_LINE: + if (x != 74) { + h = 15 - vis->vs_data[x]; + h2 = 15 - vis->vs_data[x + 1]; + if (h > h2) { + y = h; + h = h2; + h2 = y; + } + ptr = rgb_data + (h * 76) + x; + for (y = h; y <= h2; y++, ptr += 76) + *ptr = vis_scope_colors[y - 3]; + + } + else { + h = 15 - vis->vs_data[x]; + ptr = rgb_data + (h * 76) + x; + *ptr = vis_scope_colors[h]; + } + break; + case SCOPE_SOLID: + h = 15 - vis->vs_data[x]; + h2 = 9; + c = vis_scope_colors[(gint) vis->vs_data[x]]; + if (h > h2) { + y = h; + h = h2; + h2 = y; + } + ptr = rgb_data + (h * 76) + x; + for (y = h; y <= h2; y++, ptr += 76) + *ptr = c; + break; + } + } + } + + /* FIXME: The check "shouldn't" be neccessary? */ + /* if (GTK_IS_WINDOW(vis->vs_window)) { */ + GDK_THREADS_ENTER(); + gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc, + vis->vs_widget.x, vis->vs_widget.y, + vis->vs_widget.width, vis->vs_widget.height, + GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data, + 76, cmap); + GDK_THREADS_LEAVE(); + /* } else { + vis->vs_window = mainwin->window; + GDK_THREADS_ENTER(); + gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc, + vis->vs_widget.x, vis->vs_widget.y, + vis->vs_widget.width, vis->vs_widget.height, + GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data, + 76, cmap); + GDK_THREADS_LEAVE(); + } + */ + + gdk_rgb_cmap_free(cmap); +} + +void +vis_clear_data(Vis * vis) +{ + gint i; + + if (!vis) + return; + + for (i = 0; i < 75; i++) { + vis->vs_data[i] = (cfg.vis_type == VIS_SCOPE) ? 6 : 0; + vis->vs_peak[i] = 0; + } +} + +void +vis_clear(Vis * vis) +{ + gdk_window_clear_area(vis->vs_window, vis->vs_widget.x, + vis->vs_widget.y, vis->vs_widget.width, + vis->vs_widget.height); +} + +void +vis_set_window(Vis * vis, GdkWindow * window) +{ + vis->vs_window = window; +} + +Vis * +create_vis(GList ** wlist, + GdkPixmap * parent, + GdkWindow * window, + GdkGC * gc, + gint x, gint y, + gint width) +{ + Vis *vis; + + vis = g_new0(Vis, 1); + + widget_init(&vis->vs_widget, parent, gc, x, y, width, 16, 1); + widget_list_add(wlist, WIDGET(vis)); + + return vis; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/vis.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,82 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef VIS_H +#define VIS_H + +#include <glib.h> +#include <gdk/gdk.h> + +#include "widget.h" + +typedef enum { + VIS_ANALYZER, VIS_SCOPE, VIS_OFF +} VisType; + +typedef enum { + ANALYZER_NORMAL, ANALYZER_FIRE, ANALYZER_VLINES +} AnalyzerMode; + +typedef enum { + ANALYZER_LINES, ANALYZER_BARS +} AnalyzerType; + +typedef enum { + SCOPE_DOT, SCOPE_LINE, SCOPE_SOLID +} ScopeMode; + +typedef enum { + VU_NORMAL, VU_SMOOTH +} VUMode; + +typedef enum { + REFRESH_FULL, REFRESH_HALF, REFRESH_QUARTER, REFRESH_EIGTH +} RefreshRate; + +typedef enum { + FALLOFF_SLOWEST, FALLOFF_SLOW, FALLOFF_MEDIUM, FALLOFF_FAST, + FALLOFF_FASTEST +} FalloffSpeed; + +#define VIS(x) ((Vis *)(x)) +struct _Vis { + Widget vs_widget; + GdkWindow *vs_window; + gfloat vs_data[75], vs_peak[75], vs_peak_speed[75]; + gint vs_refresh_delay; +}; + +typedef struct _Vis Vis; + +void vis_draw(Widget * w); + +Vis *create_vis(GList ** wlist, GdkPixmap * parent, GdkWindow * window, + GdkGC * gc, gint x, gint y, gint width); +void vis_timeout_func(Vis * vis, guchar * data); +void vis_clear_data(Vis * vis); +void vis_clear(Vis * vis); +void vis_set_window(Vis * vis, GdkWindow * window); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/widget.c Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,263 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 "widgetcore.h" + +#include <glib.h> +#include <gdk/gdk.h> + +#include "audacious/debug.h" + + +void +widget_init(Widget * widget, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint width, gint height, gint visible) +{ + widget->parent = parent; + widget->gc = gc; + widget_set_position(widget, x, y); + widget_set_size(widget, width, height); + widget->visible = visible; + widget->redraw = TRUE; + widget->mutex = g_mutex_new(); +} + +void +widget_set_position(Widget * widget, gint x, gint y) +{ + widget->x = x; + widget->y = y; + widget_queue_redraw(widget); +} + +void +widget_set_size(Widget * widget, gint width, gint height) +{ + widget->width = width; + widget->height = height; + widget_queue_redraw(widget); +} + +void +widget_queue_redraw(Widget * widget) +{ + widget->redraw = TRUE; +} + +gboolean +widget_contains(Widget * widget, gint x, gint y) +{ + return (widget->visible && + x >= widget->x && + y >= widget->y && + x < widget->x + widget->width && + y < widget->y + widget->height); +} + +void +widget_show(Widget * widget) +{ + if (!widget) + return; + + widget->visible = TRUE; + widget_draw(widget); +} + +void +widget_hide(Widget * widget) +{ + if (!widget) + return; + + widget->visible = FALSE; +} + +gboolean +widget_is_visible(Widget * widget) +{ + if (!widget) + return FALSE; + + return widget->visible; +} + +void +widget_resize(Widget * widget, gint width, gint height) +{ + widget_set_size(widget, width, height); +} + +void +widget_move(Widget * widget, gint x, gint y) +{ + widget_lock(widget); + widget_set_position(widget, x, y); + widget_unlock(widget); +} + +void +widget_draw(Widget * widget) +{ + widget_lock(widget); + WIDGET(widget)->redraw = TRUE; + widget_unlock(widget); +} + +void +widget_draw_quick(Widget * widget) +{ + widget_lock(widget); + if (WIDGET(widget)->draw != NULL) + { + WIDGET(widget)->draw(widget); + gdk_flush(); + } + widget_unlock(widget); +} + +void +widget_list_add(GList ** list, Widget * widget) +{ + (*list) = g_list_append(*list, widget); +} + +void +handle_press_cb(GList * widget_list, GtkWidget * widget, + GdkEventButton * event) +{ + GList *wl; + + for (wl = widget_list; wl; wl = g_list_next(wl)) { + if (WIDGET(wl->data)->button_press_cb) + WIDGET(wl->data)->button_press_cb(widget, event, wl->data); + } +} + +void +handle_release_cb(GList * widget_list, GtkWidget * widget, + GdkEventButton * event) +{ + GList *wl; + + for (wl = widget_list; wl; wl = g_list_next(wl)) { + if (WIDGET(wl->data)->button_release_cb) + WIDGET(wl->data)->button_release_cb(widget, event, wl->data); + } +} + +void +handle_motion_cb(GList * widget_list, GtkWidget * widget, + GdkEventMotion * event) +{ + GList *wl; + + for (wl = widget_list; wl; wl = g_list_next(wl)) { + if (WIDGET(wl->data)->motion_cb) + WIDGET(wl->data)->motion_cb(widget, event, wl->data); + } +} + +void +handle_scroll_cb(GList * wlist, GtkWidget * widget, GdkEventScroll * event) +{ + GList *wl; + + for (wl = wlist; wl; wl = g_list_next(wl)) { + if (WIDGET(wl->data)->mouse_scroll_cb) + WIDGET(wl->data)->mouse_scroll_cb(widget, event, wl->data); + } +} + +void +widget_list_draw(GList * widget_list, gboolean * redraw, gboolean force) +{ + GList *wl; + Widget *w; + + *redraw = FALSE; + wl = widget_list; + + for (wl = widget_list; wl; wl = g_list_next(wl)) { + w = WIDGET(wl->data); + + REQUIRE_LOCK(w->mutex); + + if (!w->draw) + continue; + + if (!w->visible) + continue; + + if (w->redraw || force) { + w->draw(w); +/* w->redraw = FALSE; */ + *redraw = TRUE; + } + } +} + +void +widget_list_change_pixmap(GList * widget_list, GdkPixmap * pixmap) +{ + GList *wl; + + for (wl = widget_list; wl; wl = g_list_next(wl)) { + Widget *widget = wl->data; + widget->parent = pixmap; + widget_queue_redraw(widget); + } +} + +void +widget_list_clear_redraw(GList * widget_list) +{ + GList *wl; + + for (wl = widget_list; wl; wl = g_list_next(wl)) { + REQUIRE_LOCK(WIDGET(wl->data)->mutex); + WIDGET(wl->data)->redraw = FALSE; + } +} + +void +widget_lock(Widget * widget) +{ + g_mutex_lock(WIDGET(widget)->mutex); +} + +void +widget_unlock(Widget * widget) +{ + g_mutex_unlock(WIDGET(widget)->mutex); +} + +void +widget_list_lock(GList * widget_list) +{ + g_list_foreach(widget_list, (GFunc) widget_lock, NULL); +} + +void +widget_list_unlock(GList * widget_list) +{ + g_list_foreach(widget_list, (GFunc) widget_unlock, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/widget.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,107 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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 _WIDGETCORE_H_ +#error Please do not include me directly! Use widgetcore.h instead! +#endif + +#ifndef WIDGET_H +#define WIDGET_H + + +#include <glib.h> +#include <gdk/gdk.h> +#include <gtk/gtk.h> + + +typedef struct _Widget Widget; + + +typedef void (*WidgetButtonPressFunc) (GtkWidget *, GdkEventButton *, + gpointer); +typedef void (*WidgetButtonReleaseFunc) (GtkWidget *, GdkEventButton *, + gpointer); +typedef void (*WidgetMotionFunc) (GtkWidget *, GdkEventMotion *, gpointer); +typedef void (*WidgetDrawFunc) (Widget *); +typedef void (*WidgetScrollFunc) (GtkWidget *, GdkEventScroll *, gpointer); + + +#define WIDGET(x) ((Widget *)(x)) +struct _Widget { + GdkPixmap *parent; + GdkGC *gc; + + gint x, y; + gint width, height; + + gint visible; + gboolean redraw; + + GMutex *mutex; + + WidgetButtonPressFunc button_press_cb; + WidgetButtonReleaseFunc button_release_cb; + WidgetMotionFunc motion_cb; + WidgetDrawFunc draw; + WidgetScrollFunc mouse_scroll_cb; +}; + + +void widget_init(Widget * widget, GdkPixmap * parent, GdkGC * gc, + gint x, gint y, gint width, gint height, gint visible); + +void widget_set_position(Widget * widget, gint x, gint y); +void widget_set_size(Widget * widget, gint width, gint height); +void widget_queue_redraw(Widget * widget); + +void widget_lock(Widget * widget); +void widget_unlock(Widget * widget); + +gboolean widget_contains(Widget * widget, gint x, gint y); + +void widget_show(Widget * widget); +void widget_hide(Widget * widget); +gboolean widget_is_visible(Widget * widget); + +void widget_resize(Widget * widget, gint width, gint height); +void widget_move(Widget * widget, gint x, gint y); +void widget_draw(Widget * widget); +void widget_draw_quick(Widget * widget); + +void handle_press_cb(GList * wlist, GtkWidget * widget, + GdkEventButton * event); +void handle_release_cb(GList * wlist, GtkWidget * widget, + GdkEventButton * event); +void handle_motion_cb(GList * wlist, GtkWidget * widget, + GdkEventMotion * event); +void handle_scroll_cb(GList * wlist, GtkWidget * widget, + GdkEventScroll * event); + +void widget_list_add(GList ** list, Widget * widget); +void widget_list_draw(GList * list, gboolean * redraw, gboolean force); +void widget_list_change_pixmap(GList * list, GdkPixmap * pixmap); +void widget_list_clear_redraw(GList * list); +void widget_list_lock(GList * list); +void widget_list_unlock(GList * list); + + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/UserInterface/wa2gui/widgets/widgetcore.h Thu Sep 07 20:27:46 2006 -0700 @@ -0,0 +1,41 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2006 Audacious development team. + * + * 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 _WIDGETCORE_H_ +#define _WIDGETCORE_H_ + +#include "tbutton.h" +#include "eq_graph.h" +#include "eq_slider.h" +#include "hslider.h" +#include "menurow.h" +#include "monostereo.h" +#include "number.h" +#include "pbutton.h" +#include "playlist_list.h" +#include "playlist_slider.h" +#include "playstatus.h" +#include "sbutton.h" +#include "skin.h" +#include "svis.h" +#include "textbox.h" +#include "vis.h" +#include "widget.h" + +#endif