commit 37e584fc99e2a697e8d85845a067caab003540b6
Author: phantomjinx <[email protected]>
Date: Sat Aug 27 13:00:59 2011 +0100
Implement clarity preferences
* Preferences for changing background colour and artwork sorting
* album_model.*
* Narrowing of API and tidy up
* Implementation of sort functions
* clarity_canvas.*
* loading_complete field introduced for stopping other signal handlers
firing before the animation has completed.
plugins/clarity/Makefile.am | 1 +
plugins/clarity/album_model.c | 248 ++++++++++++++++++++-------------
plugins/clarity/album_model.h | 11 +-
plugins/clarity/clarity.xml | 38 +++---
plugins/clarity/clarity_canvas.c | 34 ++++-
plugins/clarity/clarity_canvas.h | 4 +-
plugins/clarity/clarity_preferences.c | 49 ++++---
plugins/clarity/clarity_preferences.h | 4 +-
plugins/clarity/clarity_widget.c | 76 ++++++++---
plugins/clarity/clarity_widget.h | 6 +-
plugins/clarity/plugin.c | 82 ++++++-----
plugins/clarity/plugin.h | 2 +
12 files changed, 353 insertions(+), 202 deletions(-)
---
diff --git a/plugins/clarity/Makefile.am b/plugins/clarity/Makefile.am
index 4b0fd01..c623eda 100644
--- a/plugins/clarity/Makefile.am
+++ b/plugins/clarity/Makefile.am
@@ -35,6 +35,7 @@ libclarity_la_SOURCES = plugin.c plugin.h \
clarity_widget.c
clarity_widget.h \
clarity_preview.c
clarity_preview.h \
clarity_utils.c
clarity_utils.h \
+ clarity_preferences.c
clarity_preferences.h \
clarity_context_menu.c clarity_context_menu.h \
fetchcover.c
fetchcover.h
libclarity_la_CFLAGS = $(CLUTTER_GTK_CFLAGS)
diff --git a/plugins/clarity/album_model.c b/plugins/clarity/album_model.c
index e09ec96..6db251c 100644
--- a/plugins/clarity/album_model.c
+++ b/plugins/clarity/album_model.c
@@ -32,6 +32,7 @@
#include "album_model.h"
#include "libgtkpod/prefs.h"
#include "libgtkpod/misc.h"
+#include "libgtkpod/gp_private.h"
G_DEFINE_TYPE( AlbumModel, album_model, G_TYPE_OBJECT);
@@ -42,10 +43,103 @@ struct _AlbumModelPrivate {
GHashTable *album_hash;
GList *album_key_list;
-
- gint loaded;
};
+static gchar *_create_key(Track *track) {
+ g_return_val_if_fail(track, "");
+
+ return g_strconcat(track->artist, "_", track->album, NULL);
+}
+
+static void _add_track_to_album_item(AlbumItem *item, Track *track) {
+ item->tracks = g_list_prepend(item->tracks, track);
+}
+
+static AlbumItem *_create_album_item(Track *track) {
+ AlbumItem *item = NULL;
+
+ /* Album item not found so create a new one and populate */
+ item = g_new0 (AlbumItem, 1);
+ item->albumart = NULL;
+ item->albumname = g_strdup(track->album);
+ item->artist = g_strdup(track->artist);
+ item->tracks = NULL;
+ _add_track_to_album_item(item, track);
+
+ return item;
+}
+
+/**
+ * compare_album_keys:
+ *
+ * Comparison function for comparing keys in
+ * the key list to sort them into alphabetical order.
+ * Could use g_ascii_strcasecmp directly but the NULL
+ * strings cause assertion errors.
+ *
+ * @a: first album key to compare
+ * @b: second album key to compare
+ *
+ */
+static gint _compare_album_item_keys(gchar *a, gchar *b) {
+ if (a == NULL)
+ return -1;
+ if (b == NULL)
+ return -1;
+
+ return compare_string(a, b, prefs_get_int("clarity_case_sensitive"));
+}
+
+void _index_album_item(AlbumModelPrivate *priv, gchar *album_key, AlbumItem
*item) {
+ enum GtkPodSortTypes value = prefs_get_int("clarity_sort");
+
+ g_hash_table_insert(priv->album_hash, album_key, item);
+
+ switch(value) {
+ case SORT_ASCENDING:
+ priv->album_key_list = g_list_insert_sorted(priv->album_key_list,
album_key, (GCompareFunc) _compare_album_item_keys);
+ break;
+ case SORT_DESCENDING:
+ /* Already in descending order so reverse into ascending order */
+ priv->album_key_list = g_list_reverse(priv->album_key_list);
+ /* Insert the track */
+ priv->album_key_list = g_list_insert_sorted(priv->album_key_list,
album_key, (GCompareFunc) _compare_album_item_keys);
+ /* Reverse again */
+ priv->album_key_list = g_list_reverse(priv->album_key_list);
+ break;
+ default:
+ /* NO SORT */
+
+ // Quicker to reverse, prepend then reverse back
+ priv->album_key_list = g_list_reverse(priv->album_key_list);
+ priv->album_key_list = g_list_prepend(priv->album_key_list, album_key);
+ priv->album_key_list = g_list_reverse(priv->album_key_list);
+ break;
+ }
+}
+
+static void _insert_track(AlbumModelPrivate *priv, Track *track) {
+ AlbumItem *item;
+ gchar *album_key;
+
+ album_key = _create_key(track);
+ /* Check whether an album item has already been created in connection
+ * with the track's artist and album
+ */
+ item = g_hash_table_lookup(priv->album_hash, album_key);
+ if (!item) {
+ // Create new album item
+ item = _create_album_item(track);
+ _index_album_item(priv, album_key, item);
+ }
+ else {
+ /* Album Item found in the album hash so prepend the
+ * track to the start of the track list */
+ g_free(album_key);
+ _add_track_to_album_item(item, track);
+ }
+}
+
/**
*
* clarity_widget_free_album:
@@ -53,24 +147,26 @@ struct _AlbumModelPrivate {
* Destroy an album struct once no longer needed.
*
*/
-static void album_model_free_album(AlbumItem *album) {
- if (album != NULL) {
- if (album->tracks) {
- g_list_free(album->tracks);
+static void album_model_free_album_item(AlbumItem *item) {
+ if (item) {
+ if (item->tracks) {
+ g_list_free(item->tracks);
}
+ item->tracks = NULL;
+
+ g_free(item->albumname);
+ g_free(item->artist);
- g_free(album->albumname);
- g_free(album->artist);
+ if (item->albumart)
+ g_object_unref(item->albumart);
- if (album->albumart)
- g_object_unref(album->albumart);
+ item->data = NULL;
}
}
static void album_model_finalize(GObject *gobject) {
AlbumModelPrivate *priv = ALBUM_MODEL_GET_PRIVATE(gobject);
- priv->album_key_list = g_list_remove_all(priv->album_key_list, NULL);
g_hash_table_foreach_remove(priv->album_hash, (GHRFunc) gtk_true, NULL);
g_hash_table_destroy(priv->album_hash);
g_list_free(priv->album_key_list);
@@ -92,9 +188,8 @@ static void album_model_init (AlbumModel *self) {
AlbumModelPrivate *priv;
priv = ALBUM_MODEL_GET_PRIVATE (self);
- priv->album_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify) g_free, (GDestroyNotify) album_model_free_album);
+ priv->album_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify) g_free, (GDestroyNotify) album_model_free_album_item);
priv->album_key_list = NULL;
- priv->loaded = 0;
}
@@ -112,64 +207,49 @@ void album_model_clear(AlbumModel *model) {
priv = ALBUM_MODEL_GET_PRIVATE (model);
g_hash_table_remove_all (priv->album_hash);
- g_list_free(priv->album_key_list);
- priv->album_key_list = NULL;
-}
-
-static gchar *_create_key(Track *track) {
- g_return_val_if_fail(track, "");
-
- return g_strconcat(track->artist, "_", track->album, NULL);
+ if (priv->album_key_list) {
+ g_list_free(priv->album_key_list);
+ priv->album_key_list = NULL;
+ }
}
-void album_model_add_track(AlbumModel *model, Track *track) {
- AlbumItem *album;
- gchar *album_key;
- AlbumModelPrivate *priv;
-
- priv = ALBUM_MODEL_GET_PRIVATE (model);
- album_key = _create_key(track);
- /* Check whether an album item has already been created in connection
- * with the track's artist and album
- */
- album = g_hash_table_lookup(priv->album_hash, album_key);
- if (album == NULL) {
- /* Album item not found so create a new one and populate */
- album = g_new0 (AlbumItem, 1);
- album->albumart = NULL;
- album->albumname = g_strdup(track->album);
- album->artist = g_strdup(track->artist);
- album->tracks = NULL;
- album->tracks = g_list_prepend(album->tracks, track);
-
- /* Insert the new Album Item into the hash */
- g_hash_table_insert(priv->album_hash, album_key, album);
- /* Add the key to the list for sorting and other functions */
- priv->album_key_list = g_list_prepend(priv->album_key_list, album_key);
- }
- else {
- /* Album Item found in the album hash so
- * append the track to the end of the
- * track list */
- g_free(album_key);
- album->tracks = g_list_prepend(album->tracks, track);
+void album_model_resort(AlbumModel *model, GList *tracks) {
+ AlbumModelPrivate *priv = ALBUM_MODEL_GET_PRIVATE (model);
+ enum GtkPodSortTypes value = prefs_get_int("clarity_sort");
+
+ switch (value) {
+ case SORT_ASCENDING:
+ priv->album_key_list = g_list_sort(priv->album_key_list,
(GCompareFunc) _compare_album_item_keys);
+ break;
+ case SORT_DESCENDING:
+ priv->album_key_list = g_list_sort(priv->album_key_list,
(GCompareFunc) _compare_album_item_keys);
+ priv->album_key_list = g_list_reverse(priv->album_key_list);
+ break;
+ default:
+ // No sorting needs to re-initialise the model from scratch
+ album_model_clear(model);
+ album_model_add_tracks(model, tracks);
+ break;
}
}
-void album_model_reset_loaded_index(AlbumModel *model) {
+void album_model_add_tracks(AlbumModel *model, GList *tracks) {
g_return_if_fail(model);
- AlbumModelPrivate *priv;
- priv = ALBUM_MODEL_GET_PRIVATE (model);
- priv->loaded = 0;
+ AlbumModelPrivate *priv = ALBUM_MODEL_GET_PRIVATE(model);
+ GList *trks = tracks;
+ while(trks) {
+ Track *track = trks->data;
+ _insert_track(priv, track);
+ trks = trks->next;
+ }
}
void album_model_foreach (AlbumModel *model, GFunc func, gpointer user_data) {
g_return_if_fail(model);
g_return_if_fail(func);
- AlbumModelPrivate *priv;
- priv = ALBUM_MODEL_GET_PRIVATE (model);
+ AlbumModelPrivate *priv = ALBUM_MODEL_GET_PRIVATE (model);
GList *iter = priv->album_key_list;
while(iter) {
@@ -182,61 +262,39 @@ void album_model_foreach (AlbumModel *model, GFunc func,
gpointer user_data) {
}
}
-
-gint album_model_get_size(AlbumModel *model) {
- g_return_val_if_fail(model, 0);
-
- AlbumModelPrivate *priv;
- priv = ALBUM_MODEL_GET_PRIVATE (model);
-
- return g_list_length(priv->album_key_list);
-}
-
AlbumItem *album_model_get_item(AlbumModel *model, gint index) {
g_return_val_if_fail(model, NULL);
- AlbumModelPrivate *priv;
- priv = ALBUM_MODEL_GET_PRIVATE (model);
+ AlbumModelPrivate *priv = ALBUM_MODEL_GET_PRIVATE (model);
gchar *key = g_list_nth_data(priv->album_key_list, index);
return g_hash_table_lookup(priv->album_hash, key);
}
-/**
- * compare_album_keys:
- *
- * Comparison function for comparing keys in
- * the key list to sort them into alphabetical order.
- * Could use g_ascii_strcasecmp directly but the NULL
- * strings cause assertion errors.
- *
- * @a: first album key to compare
- * @b: second album key to compare
- *
- */
-static gint _compare_album_keys(gchar *a, gchar *b) {
- if (a == NULL)
- return -1;
- if (b == NULL)
- return -1;
-
- return compare_string(a, b, prefs_get_int("cad_case_sensitive"));
-}
-
gint album_model_get_index(AlbumModel *model, Track *track) {
g_return_val_if_fail(model, -1);
- AlbumModelPrivate *priv;
- priv = ALBUM_MODEL_GET_PRIVATE (model);
+ AlbumModelPrivate *priv = ALBUM_MODEL_GET_PRIVATE (model);
gchar *trk_key = _create_key(track);
- GList *key = g_list_find_custom(priv->album_key_list, trk_key,
(GCompareFunc) _compare_album_keys);
+ GList *key_list = priv->album_key_list;
+
+ GList *key = g_list_find_custom(key_list, trk_key, (GCompareFunc)
_compare_album_item_keys);
g_return_val_if_fail (key, -1);
- gint index = g_list_position(priv->album_key_list, key);
+ gint index = g_list_position(key_list, key);
g_free(trk_key);
return index;
}
+gint album_model_get_size(AlbumModel *model) {
+ g_return_val_if_fail(model, 0);
+
+ AlbumModelPrivate *priv;
+ priv = ALBUM_MODEL_GET_PRIVATE (model);
+
+ return g_list_length(priv->album_key_list);
+}
+
#endif /* ALBUM_MODEL_C_ */
diff --git a/plugins/clarity/album_model.h b/plugins/clarity/album_model.h
index c8fd53e..2314f8f 100644
--- a/plugins/clarity/album_model.h
+++ b/plugins/clarity/album_model.h
@@ -83,16 +83,17 @@ void album_model_destroy(AlbumModel *model);
void album_model_clear(AlbumModel *model);
-void album_model_add_track(AlbumModel *model, Track *track);
-
-void album_model_reset_loaded_index(AlbumModel *model);
-
void album_model_foreach(AlbumModel *model, GFunc func, gpointer user_data);
-gint album_model_get_size(AlbumModel *model);
+void album_model_resort(AlbumModel *model, GList *tracks);
+
+void album_model_add_tracks(AlbumModel *model, GList *tracks);
AlbumItem *album_model_get_item(AlbumModel *model, gint index);
gint album_model_get_index(AlbumModel *model, Track *track);
+gint album_model_get_size(AlbumModel *model);
+
+
#endif /* ALBUM_MODEL_H_ */
diff --git a/plugins/clarity/clarity.xml b/plugins/clarity/clarity.xml
index 063c0fe..349fa82 100644
--- a/plugins/clarity/clarity.xml
+++ b/plugins/clarity/clarity.xml
@@ -31,14 +31,15 @@
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
- <object class="GtkColorButton"
id="coverart_display_bg_button">
+ <object class="GtkColorButton"
id="clarity_bg_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property
name="use_action_appearance">False</property>
- <property name="title" translatable="yes">Choose a
Different Colour for the CoverArt Display Background</property>
+ <property name="use_alpha">True</property>
+ <property name="title" translatable="yes">Choose a
Different Colour for the Clarity Background</property>
<property name="color">#000000000000</property>
- <signal name="color-set"
handler="on_coverart_dialog_bg_color_set" swapped="no"/>
+ <signal name="color-set"
handler="on_clarity_dialog_bg_color_set" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -59,14 +60,15 @@
</packing>
</child>
<child>
- <object class="GtkColorButton"
id="coverart_display_fg_button">
+ <object class="GtkColorButton"
id="clarity_fg_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property
name="use_action_appearance">False</property>
- <property name="title" translatable="yes">Choose a
Different Colour for the CoverArt Display Background</property>
+ <property name="use_alpha">True</property>
+ <property name="title" translatable="yes">Choose a
Different Colour for the Clarity Foreground</property>
<property name="color">#ffffffffffff</property>
- <signal name="color-set"
handler="on_coverart_dialog_fg_color_set" swapped="no"/>
+ <signal name="color-set"
handler="on_clarity_dialog_fg_color_set" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -94,7 +96,7 @@
<object class="GtkLabel" id="label18">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes"><b>Cover
Art Display</b></property>
+ <property name="label"
translatable="yes"><b>Clarity</b></property>
<property name="use_markup">True</property>
</object>
</child>
@@ -161,14 +163,14 @@
</packing>
</child>
<child>
- <object class="GtkRadioButton"
id="cad_ascend">
+ <object class="GtkRadioButton"
id="clarity_ascend">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property
name="receives_default">False</property>
<property
name="use_action_appearance">False</property>
<property
name="draw_indicator">True</property>
- <property name="group">cad_none</property>
- <signal name="toggled"
handler="on_cad_ascend_toggled" swapped="no"/>
+ <property
name="group">clarity_none</property>
+ <signal name="toggled"
handler="on_clarity_ascend_toggled" swapped="no"/>
<child>
<object class="GtkImage" id="image1928">
<property
name="visible">True</property>
@@ -186,14 +188,14 @@
</packing>
</child>
<child>
- <object class="GtkRadioButton"
id="cad_descend">
+ <object class="GtkRadioButton"
id="clarity_descend">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property
name="receives_default">False</property>
<property
name="use_action_appearance">False</property>
<property
name="draw_indicator">True</property>
- <property name="group">cad_none</property>
- <signal name="toggled"
handler="on_cad_descend_toggled" swapped="no"/>
+ <property
name="group">clarity_none</property>
+ <signal name="toggled"
handler="on_clarity_descend_toggled" swapped="no"/>
<child>
<object class="GtkImage" id="image1929">
<property
name="visible">True</property>
@@ -222,14 +224,14 @@
</packing>
</child>
<child>
- <object class="GtkRadioButton" id="cad_none">
+ <object class="GtkRadioButton"
id="clarity_none">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property
name="receives_default">False</property>
<property
name="use_action_appearance">False</property>
<property name="active">True</property>
<property
name="draw_indicator">True</property>
- <signal name="toggled"
handler="on_cad_none_toggled" swapped="no"/>
+ <signal name="toggled"
handler="on_clarity_none_toggled" swapped="no"/>
<child>
<object class="GtkImage" id="image1930">
<property
name="visible">True</property>
@@ -259,7 +261,7 @@
</packing>
</child>
<child>
- <object class="GtkCheckButton"
id="cad_cfg_case_sensitive">
+ <object class="GtkCheckButton"
id="clarity_cfg_case_sensitive">
<property name="label" translatable="yes">Case
sensitive sorting</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -267,7 +269,7 @@
<property
name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
- <signal name="toggled"
handler="on_cad_sort_case_sensitive_toggled" swapped="no"/>
+ <signal name="toggled"
handler="on_clarity_sort_case_sensitive_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -300,7 +302,7 @@
<object class="GtkLabel" id="display_page_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Cover Art
Display</property>
+ <property name="label" translatable="yes">Clarity</property>
</object>
<packing>
<property name="tab_fill">False</property>
diff --git a/plugins/clarity/clarity_canvas.c b/plugins/clarity/clarity_canvas.c
index f95d2cc..970b876 100644
--- a/plugins/clarity/clarity_canvas.c
+++ b/plugins/clarity/clarity_canvas.c
@@ -60,6 +60,8 @@ struct _ClarityCanvasPrivate {
gint curr_index;
gulong preview_signal;
+
+ gboolean loading_complete;
};
enum DIRECTION {
@@ -171,6 +173,7 @@ static void clarity_canvas_init(ClarityCanvas *self) {
priv->timeline = clutter_timeline_new(1600);
priv->alpha = clutter_alpha_new_full(priv->timeline,
CLUTTER_EASE_OUT_EXPO);
priv->curr_index = 0;
+ priv->loading_complete = FALSE;
}
@@ -186,7 +189,7 @@ GtkWidget *clarity_canvas_new() {
* The return value is a hexstring in the form "rrggbbaa"
*
*/
-gchar *clarity_canvas_get_background_color(ClarityCanvas *self) {
+GdkRGBA *clarity_canvas_get_background_color(ClarityCanvas *self) {
g_return_val_if_fail(CLARITY_IS_CANVAS(self), NULL);
ClarityCanvasPrivate *priv = CLARITY_CANVAS_GET_PRIVATE(self);
@@ -199,7 +202,14 @@ gchar *clarity_canvas_get_background_color(ClarityCanvas
*self) {
clutter_stage_get_color(CLUTTER_STAGE(stage), ccolor);
g_return_val_if_fail(ccolor, NULL);
- return clutter_color_to_string(ccolor);
+ GdkRGBA *rgba;
+ rgba = g_malloc(sizeof(GdkRGBA));
+ rgba->red = ((gdouble) ccolor->red) / 255;
+ rgba->green = ((gdouble) ccolor->green) / 255;
+ rgba->blue = ((gdouble) ccolor->blue) / 255;
+ rgba->alpha = ((gdouble) ccolor->alpha) / 255;
+
+ return rgba;
}
void clarity_canvas_set_background(ClarityCanvas *self, const gchar
*color_string) {
@@ -285,6 +295,12 @@ static void _display_clarity_cover(ClarityCover *ccover,
gint index) {
clutter_timeline_start (timeline);
}
+static gboolean _set_loading_complete(gpointer data) {
+ ClarityCanvasPrivate *priv = (ClarityCanvasPrivate *) data;
+ priv->loading_complete = TRUE;
+ return TRUE;
+}
+
static gboolean _create_cover_idle(gpointer data) {
AlbumItem *album_item = (AlbumItem *) data;
@@ -372,6 +388,8 @@ static gpointer _init_album_model_threaded(gpointer data) {
album_model_foreach(model, _init_album_item, cc);
+ g_idle_add_full(G_PRIORITY_LOW, _set_loading_complete, priv, NULL);
+
return NULL;
}
@@ -384,7 +402,7 @@ void clarity_canvas_init_album_model(ClarityCanvas *self,
AlbumModel *model) {
ClarityCanvasPrivate *priv = CLARITY_CANVAS_GET_PRIVATE(self);
priv->model = model;
- album_model_reset_loaded_index(model);
+ priv->loading_complete = FALSE;
g_thread_create_full(_init_album_model_threaded, self, /* user data */
0, /* stack size */
@@ -490,6 +508,8 @@ void clarity_canvas_move_left(ClarityCanvas *self, gint
increment) {
if(priv->curr_index == g_list_length(priv->covers) - 1)
return;
+ priv->loading_complete = FALSE;
+
_move(priv, MOVE_LEFT, increment);
}
@@ -500,6 +520,8 @@ void clarity_canvas_move_right(ClarityCanvas *self, gint
increment) {
if(priv->curr_index == 0)
return;
+ priv->loading_complete = FALSE;
+
_move(priv, MOVE_RIGHT, increment);
}
@@ -510,5 +532,9 @@ gint clarity_canvas_get_current_index(ClarityCanvas *self) {
return priv->curr_index;
}
-
+gboolean clarity_canvas_is_loading(ClarityCanvas *self) {
+ g_return_val_if_fail(self, FALSE);
+ ClarityCanvasPrivate *priv = CLARITY_CANVAS_GET_PRIVATE(self);
+ return !priv->loading_complete;
+}
diff --git a/plugins/clarity/clarity_canvas.h b/plugins/clarity/clarity_canvas.h
index cf22471..2a6df7d 100644
--- a/plugins/clarity/clarity_canvas.h
+++ b/plugins/clarity/clarity_canvas.h
@@ -68,7 +68,7 @@ struct _ClarityCanvasClass {
GtkWidget * clarity_canvas_new();
-gchar *clarity_canvas_get_background_color(ClarityCanvas *self);
+GdkRGBA *clarity_canvas_get_background_color(ClarityCanvas *self);
void clarity_canvas_set_background(ClarityCanvas *self, const gchar
*color_string);
@@ -82,6 +82,8 @@ void clarity_canvas_move_right(ClarityCanvas *self, gint
increment);
gint clarity_canvas_get_current_index(ClarityCanvas *self);
+gboolean clarity_canvas_is_loading(ClarityCanvas *self);
+
G_END_DECLS
#endif /* CLARITY_CANVAS_H_ */
diff --git a/plugins/clarity/clarity_preferences.c
b/plugins/clarity/clarity_preferences.c
index 33167e5..7414568 100644
--- a/plugins/clarity/clarity_preferences.c
+++ b/plugins/clarity/clarity_preferences.c
@@ -43,8 +43,8 @@ G_MODULE_EXPORT void on_clarity_dialog_bg_color_set
(GtkColorButton *widget, gpo
gchar *color_string = gdk_rgba_to_string(&color);
prefs_set_string ("clarity_bg_color", color_string);
+ gtkpod_broadcast_preference_change("clarity_bg_color", color_string);
g_free (color_string);
- coverart_display_update (FALSE);
}
/*
@@ -57,32 +57,37 @@ G_MODULE_EXPORT void on_clarity_dialog_fg_color_set
(GtkColorButton *widget, gpo
gchar *color_string = gdk_rgba_to_string(&color);
prefs_set_string ("clarity_fg_color", color_string);
+ gtkpod_broadcast_preference_change("clarity_fg_color", color_string);
g_free (color_string);
- coverart_display_update (FALSE);
}
-G_MODULE_EXPORT void on_cad_ascend_toggled(GtkToggleButton *togglebutton,
gpointer user_data) {
+static void _set_sort_preference(gint order) {
+ prefs_set_int("clarity_sort", order);
+ gtkpod_broadcast_preference_change("clarity_sort", &order);
+}
+
+G_MODULE_EXPORT void on_clarity_ascend_toggled(GtkToggleButton *togglebutton,
gpointer user_data) {
if (gtk_toggle_button_get_active(togglebutton))
- coverart_display_sort(SORT_ASCENDING);
+ _set_sort_preference(SORT_ASCENDING);
}
-G_MODULE_EXPORT void on_cad_descend_toggled(GtkToggleButton *togglebutton,
gpointer user_data) {
+G_MODULE_EXPORT void on_clarity_descend_toggled(GtkToggleButton *togglebutton,
gpointer user_data) {
if (gtk_toggle_button_get_active(togglebutton))
- coverart_display_sort(SORT_DESCENDING);
+ _set_sort_preference(SORT_DESCENDING);
}
-G_MODULE_EXPORT void on_cad_none_toggled(GtkToggleButton *togglebutton,
gpointer user_data) {
+G_MODULE_EXPORT void on_clarity_none_toggled(GtkToggleButton *togglebutton,
gpointer user_data) {
if (gtk_toggle_button_get_active(togglebutton))
- coverart_display_sort(SORT_NONE);
+ _set_sort_preference(SORT_NONE);
}
-G_MODULE_EXPORT void on_cad_sort_case_sensitive_toggled(GtkToggleButton
*togglebutton, gpointer user_data) {
+G_MODULE_EXPORT void on_clarity_sort_case_sensitive_toggled(GtkToggleButton
*togglebutton, gpointer user_data) {
gboolean val = gtk_toggle_button_get_active(togglebutton);
- prefs_set_int("cad_case_sensitive", val);
- gtkpod_broadcast_preference_change("cad_case_sensitive", val);
+ prefs_set_int("clarity_case_sensitive", val);
+ gtkpod_broadcast_preference_change("clarity_case_sensitive", &val);
}
-GtkWidget *init_cover_preferences(gchar *gladepath) {
+GtkWidget *init_clarity_preferences(const gchar *gladepath, ClarityWidget *cw)
{
GtkWidget *notebook;
GtkBuilder *pref_xml;
GtkWidget *coverart_bgcolorselect_button;
@@ -93,36 +98,36 @@ GtkWidget *init_cover_preferences(gchar *gladepath) {
pref_xml = gtkpod_builder_xml_new(gladepath);
win = gtkpod_builder_xml_get_widget(pref_xml, "preference_window");
notebook = gtkpod_builder_xml_get_widget(pref_xml,
"cover_settings_notebook");
- coverart_bgcolorselect_button = gtkpod_builder_xml_get_widget (pref_xml,
"coverart_display_bg_button");
- coverart_fgcolorselect_button = gtkpod_builder_xml_get_widget (pref_xml,
"coverart_display_fg_button");
+ coverart_bgcolorselect_button = gtkpod_builder_xml_get_widget (pref_xml,
"clarity_bg_button");
+ coverart_fgcolorselect_button = gtkpod_builder_xml_get_widget (pref_xml,
"clarity_fg_button");
g_object_ref(notebook);
gtk_container_remove(GTK_CONTAINER (win), notebook);
- color = coverart_get_background_display_color();
+ color = clarity_widget_get_background_display_color(cw);
gtk_color_button_set_rgba
(GTK_COLOR_BUTTON(coverart_bgcolorselect_button), color);
gdk_rgba_free(color);
- color = coverart_get_foreground_display_color();
+ color = clarity_widget_get_foreground_display_color(cw);
gtk_color_button_set_rgba
(GTK_COLOR_BUTTON(coverart_fgcolorselect_button), color);
gdk_rgba_free(color);
- switch (prefs_get_int("cad_sort")) {
+ switch (prefs_get_int("clarity_sort")) {
case SORT_ASCENDING:
- w = gtkpod_builder_xml_get_widget(pref_xml, "cad_ascend");
+ w = gtkpod_builder_xml_get_widget(pref_xml, "clarity_ascend");
break;
case SORT_DESCENDING:
- w = gtkpod_builder_xml_get_widget(pref_xml, "cad_descend");
+ w = gtkpod_builder_xml_get_widget(pref_xml, "clarity_descend");
break;
default:
- w = gtkpod_builder_xml_get_widget(pref_xml, "cad_none");
+ w = gtkpod_builder_xml_get_widget(pref_xml, "clarity_none");
break;
}
if (w)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE);
- if ((w = gtkpod_builder_xml_get_widget(pref_xml,
"cad_cfg_case_sensitive"))) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
prefs_get_int("cad_case_sensitive"));
+ if ((w = gtkpod_builder_xml_get_widget(pref_xml,
"clarity_cfg_case_sensitive"))) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
prefs_get_int("clarity_case_sensitive"));
}
gtk_builder_connect_signals(pref_xml, NULL);
diff --git a/plugins/clarity/clarity_preferences.h
b/plugins/clarity/clarity_preferences.h
index 2b102fa..5316083 100644
--- a/plugins/clarity/clarity_preferences.h
+++ b/plugins/clarity/clarity_preferences.h
@@ -29,6 +29,8 @@
#ifndef CLARITY_PREFERENCES_H_
#define CLARITY_PREFERENCES_H_
-GtkWidget *init_clarity_preferences();
+#include "clarity_widget.h"
+
+GtkWidget *init_clarity_preferences(const gchar *gladepath, ClarityWidget *cw);
#endif /* CLARITY_PREFERENCES_H_ */
diff --git a/plugins/clarity/clarity_widget.c b/plugins/clarity/clarity_widget.c
index eed716e..8636761 100644
--- a/plugins/clarity/clarity_widget.c
+++ b/plugins/clarity/clarity_widget.c
@@ -72,7 +72,6 @@ enum {
* track updated
* change background
* text
- * select cover
* set cover from file
* sort
* preferences
@@ -221,6 +220,21 @@ static void _init_slider_range(ClarityWidgetPrivate *priv)
{
g_signal_handler_unblock(G_OBJECT(priv->cdslider), priv->slider_signal_id);
}
+static void _set_background(ClarityWidget *self) {
+ gchar *hex_string;
+
+ hex_string = "#FFFFFF";
+
+ if (!prefs_get_string_value("clarity_bg_color", NULL))
+ hex_string = "#000000";
+ else
+ prefs_get_string_value("clarity_bg_color", &hex_string);
+
+ ClarityWidgetPrivate *priv = CLARITY_WIDGET_GET_PRIVATE(self);
+
+ clarity_canvas_set_background(CLARITY_CANVAS(priv->draw_area), hex_string);
+}
+
static void clarity_widget_class_init (ClarityWidgetClass *klass) {
GObjectClass *gobject_class;
@@ -243,7 +257,7 @@ static void clarity_widget_init (ClarityWidget *self) {
G_CALLBACK(_on_scrolling_covers_cb),
priv);
- clarity_widget_set_background(self);
+ _set_background(self);
priv->leftbutton = gtk_button_new_with_label("<");
gtk_widget_set_name(priv->leftbutton, LEFT_BUTTON);
@@ -294,7 +308,7 @@ static void clarity_widget_clear(ClarityWidget *self) {
album_model_clear(priv->album_model);
}
-static void clarity_widget_init_tracks(ClarityWidget *cw, GList *tracks) {
+static void _init_tracks(ClarityWidget *cw, GList *tracks) {
g_return_if_fail(CLARITY_IS_WIDGET(cw));
if (!tracks)
@@ -302,40 +316,59 @@ static void clarity_widget_init_tracks(ClarityWidget *cw,
GList *tracks) {
ClarityWidgetPrivate *priv = CLARITY_WIDGET_GET_PRIVATE(cw);
- while (tracks) {
- Track *track = tracks->data;
- album_model_add_track(priv->album_model, track);
- tracks = tracks->next;
- }
+ album_model_add_tracks(priv->album_model, tracks);
clarity_canvas_init_album_model(CLARITY_CANVAS(priv->draw_area),
priv->album_model);
_init_slider_range(priv);
}
-void clarity_widget_set_background(ClarityWidget *self) {
- gchar *hex_string;
+GdkRGBA *clarity_widget_get_background_display_color(ClarityWidget *self) {
+ g_return_val_if_fail(CLARITY_IS_WIDGET(self), NULL);
- hex_string = "#FFFFFF";
+ ClarityWidgetPrivate *priv = CLARITY_WIDGET_GET_PRIVATE(self);
- if (!prefs_get_string_value("clarity_bg_color", NULL))
- hex_string = "#000000";
- else
- prefs_get_string_value("clarity_bg_color", &hex_string);
+ return
clarity_canvas_get_background_color(CLARITY_CANVAS(priv->draw_area));
+}
+
+GdkRGBA *clarity_widget_get_foreground_display_color(ClarityWidget *self) {
+ g_return_val_if_fail(CLARITY_IS_WIDGET(self), NULL);
ClarityWidgetPrivate *priv = CLARITY_WIDGET_GET_PRIVATE(self);
- clarity_canvas_set_background(CLARITY_CANVAS(priv->draw_area), hex_string);
+ return
clarity_canvas_get_background_color(CLARITY_CANVAS(priv->draw_area));
}
-void clarity_widget_preference_changed_cb(GtkPodApp *app, gpointer pfname,
gint32 value, gpointer data) {
+static void _resort_albums(ClarityWidget *self) {
+ g_return_if_fail(CLARITY_IS_WIDGET(self));
+ ClarityWidgetPrivate *priv = CLARITY_WIDGET_GET_PRIVATE(self);
+
+ // Need to clear away the graphics and start again
+ clarity_canvas_clear(CLARITY_CANVAS(priv->draw_area));
+
+ // Resort the albums
+ Playlist *playlist = gtkpod_get_current_playlist();
+ if (playlist) {
+ album_model_resort(priv->album_model, playlist->members);
+
+ // Re-init the graphics
+ clarity_canvas_init_album_model(CLARITY_CANVAS(priv->draw_area),
priv->album_model);
+
+ // Reset the slider and buttons
+ _init_slider_range(priv);
+ }
+}
+
+void clarity_widget_preference_changed_cb(GtkPodApp *app, gpointer pfname,
gpointer value, gpointer data) {
g_return_if_fail(CLARITY_IS_WIDGET(data));
ClarityWidget *cw = CLARITY_WIDGET(data);
gchar *pref_name = pfname;
if (g_str_equal(pref_name, "clarity_bg_color"))
- clarity_widget_set_background(cw);
+ _set_background(cw);
+ else if (g_str_equal(pref_name, "clarity_sort"))
+ _resort_albums(cw);
}
void clarity_widget_playlist_selected_cb(GtkPodApp *app, gpointer pl, gpointer
data) {
@@ -353,7 +386,7 @@ void clarity_widget_playlist_selected_cb(GtkPodApp *app,
gpointer pl, gpointer d
if (!tracks)
return;
- clarity_widget_init_tracks(cw, tracks);
+ _init_tracks(cw, tracks);
}
void clarity_widget_tracks_selected_cb(GtkPodApp *app, gpointer tks, gpointer
data) {
@@ -366,6 +399,11 @@ void clarity_widget_tracks_selected_cb(GtkPodApp *app,
gpointer tks, gpointer da
if (!tracks)
return;
+ ClarityCanvas *ccanvas = CLARITY_CANVAS(priv->draw_area);
+
+ if (clarity_canvas_is_loading(ccanvas))
+ return;
+
gint album_index = album_model_get_index(priv->album_model, tracks->data);
gtk_range_set_value(GTK_RANGE (priv->cdslider), album_index);
}
diff --git a/plugins/clarity/clarity_widget.h b/plugins/clarity/clarity_widget.h
index 5debcb8..a6c216f 100644
--- a/plugins/clarity/clarity_widget.h
+++ b/plugins/clarity/clarity_widget.h
@@ -65,13 +65,15 @@ struct _ClarityWidgetClass {
};
-void clarity_widget_set_background(ClarityWidget *self);
+GdkRGBA *clarity_widget_get_background_display_color(ClarityWidget *self);
+
+GdkRGBA *clarity_widget_get_foreground_display_color(ClarityWidget *self);
GtkWidget * clarity_widget_new();
// Signal callbacks
-void clarity_widget_preference_changed_cb(GtkPodApp *app, gpointer pfname,
gint32 value, gpointer data);
+void clarity_widget_preference_changed_cb(GtkPodApp *app, gpointer pfname,
gpointer value, gpointer data);
void clarity_widget_playlist_selected_cb(GtkPodApp *app, gpointer pl, gpointer
data);
void clarity_widget_track_removed_cb(GtkPodApp *app, gpointer tk, gpointer
data);
void clarity_widget_tracks_selected_cb(GtkPodApp *app, gpointer tks, gpointer
data);
diff --git a/plugins/clarity/plugin.c b/plugins/clarity/plugin.c
index 11c2981..8e5f9ea 100644
--- a/plugins/clarity/plugin.c
+++ b/plugins/clarity/plugin.c
@@ -39,7 +39,7 @@
#include "libgtkpod/directories.h"
#include "plugin.h"
#include "clarity_widget.h"
-//#include "clarity_preferences.h"
+#include "clarity_preferences.h"
#define TAB_NAME "Clarity"
@@ -50,11 +50,11 @@ static GtkActionEntry cover_actions[] =
{ };
static void set_default_preferences() {
- if (!prefs_get_string_value("clarity_display_bg_color", NULL))
- prefs_set_string("clarity_display_bg_color", "#000000");
+ if (!prefs_get_string_value("clarity_bg_color", NULL))
+ prefs_set_string("clarity_bg_color", "#000000");
- if (!prefs_get_string_value("clarity_display_fg_color", NULL))
- prefs_set_string("clarity_display_fg_color", "#FFFFFF");
+ if (!prefs_get_string_value("clarity_fg_color", NULL))
+ prefs_set_string("clarity_fg_color", "#FFFFFF");
}
static gboolean activate_plugin(AnjutaPlugin *plugin) {
@@ -88,18 +88,18 @@ static gboolean activate_plugin(AnjutaPlugin *plugin) {
gtk_scrolled_window_set_policy(clarity_plugin->cover_window,
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(clarity_plugin->cover_window,
GTK_SHADOW_IN);
- GtkWidget* cw = clarity_widget_new ();
- gtk_scrolled_window_add_with_viewport(clarity_plugin->cover_window, cw);
+ clarity_plugin->clarity_widget = CLARITY_WIDGET(clarity_widget_new ());
+ gtk_scrolled_window_add_with_viewport(clarity_plugin->cover_window,
GTK_WIDGET(clarity_plugin->clarity_widget));
gtk_widget_show_all(GTK_WIDGET(clarity_plugin->cover_window));
anjuta_shell_add_widget(plugin->shell,
GTK_WIDGET(clarity_plugin->cover_window), "ClarityPlugin", "Cover Artwork",
NULL, ANJUTA_SHELL_PLACEMENT_CENTER, NULL);
- g_signal_connect (gtkpod_app, SIGNAL_PREFERENCE_CHANGE, G_CALLBACK
(clarity_widget_preference_changed_cb), cw);
- g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_SELECTED, G_CALLBACK
(clarity_widget_playlist_selected_cb), cw);
- g_signal_connect (gtkpod_app, SIGNAL_TRACK_REMOVED, G_CALLBACK
(clarity_widget_track_removed_cb), cw);
- g_signal_connect (gtkpod_app, SIGNAL_TRACKS_DISPLAYED, G_CALLBACK
(clarity_widget_tracks_selected_cb), cw);
- g_signal_connect (gtkpod_app, SIGNAL_TRACKS_SELECTED, G_CALLBACK
(clarity_widget_tracks_selected_cb), cw);
- g_signal_connect (gtkpod_app, SIGNAL_TRACK_UPDATED, G_CALLBACK
(clarity_widget_track_updated_cb), cw);
- g_signal_connect (gtkpod_app, SIGNAL_TRACK_ADDED, G_CALLBACK
(clarity_widget_track_added_cb), cw);
+ g_signal_connect (gtkpod_app, SIGNAL_PREFERENCE_CHANGE, G_CALLBACK
(clarity_widget_preference_changed_cb), clarity_plugin->clarity_widget);
+ g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_SELECTED, G_CALLBACK
(clarity_widget_playlist_selected_cb), clarity_plugin->clarity_widget);
+ g_signal_connect (gtkpod_app, SIGNAL_TRACK_REMOVED, G_CALLBACK
(clarity_widget_track_removed_cb), clarity_plugin->clarity_widget);
+ g_signal_connect (gtkpod_app, SIGNAL_TRACKS_DISPLAYED, G_CALLBACK
(clarity_widget_tracks_selected_cb), clarity_plugin->clarity_widget);
+ g_signal_connect (gtkpod_app, SIGNAL_TRACKS_SELECTED, G_CALLBACK
(clarity_widget_tracks_selected_cb), clarity_plugin->clarity_widget);
+ g_signal_connect (gtkpod_app, SIGNAL_TRACK_UPDATED, G_CALLBACK
(clarity_widget_track_updated_cb), clarity_plugin->clarity_widget);
+ g_signal_connect (gtkpod_app, SIGNAL_TRACK_ADDED, G_CALLBACK
(clarity_widget_track_added_cb), clarity_plugin->clarity_widget);
return TRUE; /* FALSE if activation failed */
}
@@ -109,6 +109,14 @@ static gboolean deactivate_plugin(AnjutaPlugin *plugin) {
ClarityPlugin *clarity_plugin;
clarity_plugin = (ClarityPlugin*) plugin;
+
+ g_signal_handlers_disconnect_by_func(plugin->shell, G_CALLBACK
(clarity_widget_preference_changed_cb), clarity_plugin->clarity_widget);
+ g_signal_handlers_disconnect_by_func(plugin->shell, G_CALLBACK
(clarity_widget_playlist_selected_cb), clarity_plugin->clarity_widget);
+ g_signal_handlers_disconnect_by_func(plugin->shell, G_CALLBACK
(clarity_widget_track_removed_cb), clarity_plugin->clarity_widget);
+ g_signal_handlers_disconnect_by_func(plugin->shell, G_CALLBACK
(clarity_widget_tracks_selected_cb), clarity_plugin->clarity_widget);
+ g_signal_handlers_disconnect_by_func(plugin->shell, G_CALLBACK
(clarity_widget_track_updated_cb), clarity_plugin->clarity_widget);
+ g_signal_handlers_disconnect_by_func(plugin->shell, G_CALLBACK
(clarity_widget_track_added_cb), clarity_plugin->clarity_widget);
+
ui = anjuta_shell_get_ui(plugin->shell, NULL);
/* Remove widgets from Shell */
@@ -117,6 +125,10 @@ static gboolean deactivate_plugin(AnjutaPlugin *plugin) {
/* Unmerge UI */
anjuta_ui_unmerge(ui, clarity_plugin->uiid);
+ /* Destroy the widget */
+ gtk_widget_destroy(GTK_WIDGET(clarity_plugin->clarity_widget));
+ clarity_plugin->clarity_widget = NULL;
+
/* Remove Action groups */
anjuta_ui_remove_action_group(ui, clarity_plugin->action_group);
@@ -144,33 +156,33 @@ static void clarity_plugin_class_init(GObjectClass
*klass) {
}
static void ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences*
prefs, GError** e) {
-// GdkPixbuf *pixbuf;
-// GError *error = NULL;
-//
-// ClarityPlugin* plugin = CLARITY_PLUGIN(ipref);
-// plugin->prefs = init_cover_preferences(plugin->gladepath);
-// if (plugin->prefs == NULL)
-// return;
-//
-// pixbuf = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
DEFAULT_COVER_ICON, 48, 0, &error);
-//
-// if (!pixbuf) {
-// g_warning ("Couldn't load icon: %s", error->message);
-// g_error_free(error);
-// }
-// anjuta_preferences_dialog_add_page(ANJUTA_PREFERENCES_DIALOG
(anjuta_preferences_get_dialog (prefs)), "gtkpod-clarity-settings",
_(TAB_NAME), pixbuf, plugin->prefs);
-// g_object_unref(pixbuf);
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
+
+ ClarityPlugin* plugin = CLARITY_PLUGIN(ipref);
+ plugin->prefs = init_clarity_preferences(plugin->gladepath,
plugin->clarity_widget);
+ if (plugin->prefs == NULL)
+ return;
+
+ pixbuf = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
DEFAULT_COVER_ICON, 48, 0, &error);
+
+ if (!pixbuf) {
+ g_warning ("Couldn't load icon: %s", error->message);
+ g_error_free(error);
+ }
+ anjuta_preferences_dialog_add_page(ANJUTA_PREFERENCES_DIALOG
(anjuta_preferences_get_dialog (prefs)), "gtkpod-clarity-settings",
_(TAB_NAME), pixbuf, plugin->prefs);
+ g_object_unref(pixbuf);
}
static void ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences*
prefs, GError** e) {
-// anjuta_preferences_remove_page(prefs, _(TAB_NAME));
-// ClarityPlugin* plugin = CLARITY_PLUGIN(ipref);
-// gtk_widget_destroy(plugin->prefs);
+ anjuta_preferences_remove_page(prefs, _(TAB_NAME));
+ ClarityPlugin* plugin = CLARITY_PLUGIN(ipref);
+ gtk_widget_destroy(plugin->prefs);
}
static void ipreferences_iface_init(IAnjutaPreferencesIface* iface) {
-// iface->merge = ipreferences_merge;
-// iface->unmerge = ipreferences_unmerge;
+ iface->merge = ipreferences_merge;
+ iface->unmerge = ipreferences_unmerge;
}
ANJUTA_PLUGIN_BEGIN (ClarityPlugin, clarity_plugin);
diff --git a/plugins/clarity/plugin.h b/plugins/clarity/plugin.h
index 1b9b746..f91f2fc 100644
--- a/plugins/clarity/plugin.h
+++ b/plugins/clarity/plugin.h
@@ -36,6 +36,7 @@
#include <libanjuta/anjuta-plugin.h>
#include "clarity_utils.h"
+#include "clarity_widget.h"
extern GType clarity_plugin_get_type (GTypeModule *module);
#define CLARITY_TYPE_PLUGIN (clarity_plugin_get_type (NULL))
@@ -51,6 +52,7 @@ typedef struct _ClarityPluginClass ClarityPluginClass;
struct _ClarityPlugin {
AnjutaPlugin parent;
GtkScrolledWindow *cover_window;
+ ClarityWidget *clarity_widget;
gint uiid;
GtkActionGroup *action_group;
GtkWidget *prefs;
------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2