changeset 3390:3a77e835874f

merge
author Cristi Magherusan <majeru@atheme-project.org>
date Sun, 12 Aug 2007 20:03:43 +0300
parents c8d0d7bf26d4 (current diff) 3da640de0e99 (diff)
children 0afbafec6cd8
files src/audacious/Makefile src/audacious/plugin.h
diffstat 17 files changed, 283 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/src/audacious/Makefile	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/Makefile	Sun Aug 12 20:03:43 2007 +0300
@@ -36,6 +36,7 @@
 HEADERS = \
 	auddrct.h \
 	configdb.h \
+	custom_uri.h \
 	dbus.h \
 	discovery.h \
 	eventqueue.h \
@@ -68,6 +69,7 @@
 	auddrct.c \
 	build_stamp.c \
 	configdb.c \
+	custom_uri.c \
 	discovery.c \
 	dnd.c \
 	dock.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audacious/custom_uri.c	Sun Aug 12 20:03:43 2007 +0300
@@ -0,0 +1,59 @@
+/*
+ * Audacious
+ * Copyright (c) 2007 William Pitcock
+ *
+ * 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; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses>.
+ *
+ * The Audacious team does not consider modular code linking to
+ * Audacious or using our public API to be a derived work.
+ */
+
+#include "custom_uri.h"
+
+mowgli_dictionary_t *uri_type_dict = NULL;
+
+void uri_set_plugin(const gchar *uri, InputPlugin *ip)
+{
+    g_return_if_fail(uri != NULL);
+    g_return_if_fail(ip != NULL);
+
+    if (uri_type_dict == NULL)
+        uri_type_dict = mowgli_dictionary_create(strcasecmp);
+    else if (mowgli_dictionary_find(uri_type_dict, uri))
+        mowgli_dictionary_delete(uri_type_dict, uri);
+    mowgli_dictionary_add(uri_type_dict, uri, ip);
+}
+
+InputPlugin *uri_get_plugin(const gchar *filename)
+{
+    gchar *uri, *pos;
+    InputPlugin *ip;
+
+    if (filename == NULL)
+        return NULL;
+
+    if (uri_type_dict == NULL)
+        return NULL;
+
+    pos = strstr(filename, "://");
+    if (pos)
+        uri = g_strndup(filename, pos - filename + 3);
+    else
+        return NULL;
+
+    ip = mowgli_dictionary_retrieve(uri_type_dict, uri);
+ 
+    g_free(uri);
+    
+    return ip;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audacious/custom_uri.h	Sun Aug 12 20:03:43 2007 +0300
@@ -0,0 +1,36 @@
+/*
+ * Audacious
+ * Copyright (c) 2007 William Pitcock
+ *
+ * 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; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses>.
+ *
+ * The Audacious team does not consider modular code linking to
+ * Audacious or using our public API to be a derived work.
+ */
+
+#include <glib.h>
+#include <mowgli.h>
+
+#include <audacious/plugin.h>
+
+#ifndef __AUDACIOUS_CUSTOM_URI_H__
+#define __AUDACIOUS_CUSTOM_URI_H__
+
+G_BEGIN_DECLS
+
+InputPlugin *uri_get_plugin(const gchar *filename);
+void uri_set_plugin(const gchar *uri, InputPlugin *ip);
+
+G_END_DECLS
+
+#endif
--- a/src/audacious/dbus-service.h	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/dbus-service.h	Sun Aug 12 20:03:43 2007 +0300
@@ -53,7 +53,6 @@
 gboolean mpris_player_play(MprisPlayer *obj, GError **error);
 gboolean mpris_player_repeat(MprisPlayer *obj, gboolean rpt, GError **error);
 gboolean mpris_player_quit(MprisPlayer *obj, GError **error);
-gboolean mpris_player_disconnect(MprisPlayer *obj, GError **error);
 gboolean mpris_player_get_status(MprisPlayer *obj, gint *status,
                                  GError **error);
 gboolean mpris_player_get_metadata(MprisTrackList *obj, gint pos,
@@ -70,13 +69,11 @@
     TRACK_CHANGE_SIG,
     STATUS_CHANGE_SIG,
     CAPS_CHANGE_SIG,
-    DISCONNECTED,
     LAST_SIG
 };
 gboolean mpris_player_emit_track_change(MprisPlayer *obj, GError **error);
 gboolean mpris_player_emit_status_change(MprisPlayer *obj, GError **error);
 gboolean mpris_player_emit_caps_change(MprisPlayer *obj, GError **error);
-gboolean mpris_player_emit_disconnected(MprisPlayer *obj, GError **error);
 
 // MPRIS /TrackList
 gboolean mpris_tracklist_get_metadata(MprisTrackList *obj, gint pos,
--- a/src/audacious/dbus.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/dbus.c	Sun Aug 12 20:03:43 2007 +0300
@@ -208,13 +208,9 @@
     return TRUE;
 }
 gboolean mpris_player_quit(MprisPlayer *obj, GError **error) {
-	// TODO: emit disconnected signal
 	mainwin_quit_cb();
     return TRUE;
 }
-gboolean mpris_player_disconnect(MprisPlayer *obj, GError **error) {
-	return FALSE;
-}
 gboolean mpris_player_get_status(MprisPlayer *obj, gint *status,
                                  GError **error) {
     return FALSE;
@@ -258,11 +254,6 @@
     return TRUE;
 }
 
-gboolean mpris_player_emit_disconnected(MprisPlayer *obj, GError **error) {
-	g_signal_emit(obj, signals[DISCONNECTED], 0, NULL);
-	return TRUE;
-}
-
 // MPRIS /TrackList
 gboolean mpris_tracklist_get_metadata(MprisTrackList *obj, gint pos,
                                       GHashTable *metadata, GError **error) {
--- a/src/audacious/input.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/input.c	Sun Aug 12 20:03:43 2007 +0300
@@ -369,6 +369,26 @@
     if (tmp != NULL && g_ascii_isdigit(*(tmp + 1)))
         *tmp = '\0';
 
+    /* Check for plugins with custom URI:// strings */
+    /* cue:// cdda:// tone:// tact:// */
+    if ((ip = uri_get_plugin(filename)) != NULL &&
+        input_is_enabled(ip->filename) == TRUE)
+    {
+        if (ip->is_our_file != NULL)
+            ret = ip->is_our_file(filename_proxy);
+        else
+            ret = 0;
+        if (ret > 0)
+        {
+            g_free(filename_proxy);
+            pr = g_new0(ProbeResult, 1);
+            pr->ip = ip;
+            return pr;
+        }
+        g_free(filename_proxy);
+        return NULL;
+    }
+
     /* CD-Audio uses cdda:// dummy paths, no filedescriptor handling for it */
     /* also cuesheet uses cue:// */
     if (!g_strncasecmp(filename, "cdda://", 7) ||
@@ -609,7 +629,7 @@
 
         tuple_associate_string(tuple, "file-path", g_path_get_dirname(tmp));
 
-        tmp = tuple_formatter_process_string(tuple, cfg.gentitle_format);
+        tmp = tuple_formatter_process_string(tuple, get_gentitle_format());
         if (tmp != NULL && *tmp != '\0') {
             (*title) = str_to_utf8(tmp);
             g_free(tmp);
--- a/src/audacious/main.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/main.c	Sun Aug 12 20:03:43 2007 +0300
@@ -453,7 +453,7 @@
 }
 
 const gchar *
-xmms_get_gentitle_format(void)
+get_gentitle_format(void)
 {
     guint titlestring_preset = cfg.titlestring_preset;
 
--- a/src/audacious/mpris_player.xml	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/mpris_player.xml	Sun Aug 12 20:03:43 2007 +0300
@@ -42,9 +42,6 @@
         <method name="Quit">
             <annotation name="org.freedesktop.DBus.GLib.NoReply" value=""/>
         </method>
-        <method name="Disconnect">
-            <annotation name="org.freedesktop.DBus.GLib.NoReply" value=""/>
-        </method>
         <method name="GetStatus">
             <arg type="i" direction="out" />
         </method>
@@ -78,6 +75,5 @@
         <signal name="CapsChange">
             <arg type="i" />
         </signal>
-		<signal name="Disconnected" />
     </interface>
 </node>
--- a/src/audacious/playback.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/playback.c	Sun Aug 12 20:03:43 2007 +0300
@@ -224,7 +224,10 @@
             playback->plugin->stop(playback);
 
         if (playback->thread != NULL)
+        {
             g_thread_join(playback->thread);
+            playback->thread = NULL;
+        }
 
         free_vis_data();
         ip_data.paused = FALSE;
@@ -334,7 +337,6 @@
     playback->plugin = entry->decoder;
     playback->output = &psuedo_output_plugin;
     playback->filename = g_strdup(entry->filename);
-    playback->thread = g_thread_self();
     playback->pb_ready_mutex = g_mutex_new();
     playback->pb_ready_cond = g_cond_new();
     playback->pb_ready_val = 0;
@@ -342,7 +344,7 @@
     
     set_current_input_playback(playback);
 
-    g_thread_create(playback_monitor_thread, playback, TRUE, NULL);
+    playback->thread = g_thread_create(playback_monitor_thread, playback, TRUE, NULL);
 
     return TRUE;
 }
--- a/src/audacious/playlist.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/playlist.c	Sun Aug 12 20:03:43 2007 +0300
@@ -238,7 +238,8 @@
 
     /* entry is still around */
     formatter = tuple_get_string(tuple, "formatter");
-    entry->title = tuple_formatter_process_string(tuple, formatter ? formatter : cfg.gentitle_format);
+    entry->title = tuple_formatter_process_string(tuple, formatter ?
+                                                  formatter : get_gentitle_format());
     entry->length = tuple_get_int(tuple, "length");
     entry->tuple = tuple;
 
@@ -674,7 +675,8 @@
     PLAYLIST_UNLOCK( playlist->mutex );
     if (tuple != NULL) {
         const gchar *formatter = tuple_get_string(tuple, "formatter");
-        entry->title = tuple_formatter_process_string(tuple, formatter ? formatter : cfg.gentitle_format);
+        entry->title = tuple_formatter_process_string(tuple, formatter ?
+                                                      formatter : get_gentitle_format());
         entry->length = tuple_get_int(tuple, "length");
         entry->tuple = tuple;
     }
@@ -919,7 +921,10 @@
 guint
 playlist_add_url(Playlist * playlist, const gchar * url)
 {
-    return playlist_ins_url(playlist, url, -1);
+    guint entries;
+    entries = playlist_ins_url(playlist, url, -1);
+//    printf("playlist_add_url: entries = %d\n", entries);
+    return entries;
 }
 
 guint
@@ -965,19 +970,17 @@
                     gint pos)
 {
     gchar *tmp;
-    gint i = 1, entries = 0;
-    gboolean first = TRUE;
-    guint firstpos = 0;
-    gboolean success = FALSE;
+    gint entries = 0;
     gchar *decoded = NULL;
 
     g_return_val_if_fail(playlist != NULL, 0);
     g_return_val_if_fail(string != NULL, 0);
 
-    playlistwin_update_list(playlist);
+//    playlistwin_update_list(playlist); // is this necessary? --yaz
 
     while (*string) {
         GList *node;
+        guint i = 0;
         tmp = strchr(string, '\n');
         if (tmp) {
             if (*(tmp - 1) == '\r')
@@ -994,8 +997,7 @@
             if (is_playlist_name(decoded)) {
                 i = playlist_load_ins(playlist, decoded, pos);
             }
-            else {
-                success = playlist_ins(playlist, decoded, pos);
+            else if (playlist_ins(playlist, decoded, pos)) {
                 i = 1;
             }
         }
@@ -1008,11 +1010,6 @@
 
         entries += i;
 
-        if (first) {
-            first = FALSE;
-            firstpos = pos;
-        }
-
         if (pos >= 0)
             pos += i;
         if (!tmp)
@@ -1601,14 +1598,14 @@
 gboolean
 playlist_load(Playlist * playlist, const gchar * filename)
 {
-    gboolean ret = FALSE;
+    guint ret = 0;
     g_return_val_if_fail(playlist != NULL, FALSE);
 
     playlist->loading_playlist = TRUE;
     ret = playlist_load_ins(playlist, filename, -1);
     playlist->loading_playlist = FALSE;
 
-    return ret;
+    return ret ? TRUE : FALSE;
 }
 
 void
@@ -1751,7 +1748,8 @@
 {
     PlaylistContainer *plc;
     gchar *ext;
-
+    gint old_len, new_len;
+    
     g_return_val_if_fail(playlist != NULL, 0);
     g_return_val_if_fail(filename != NULL, 0);
 
@@ -1761,12 +1759,14 @@
     g_return_val_if_fail(plc != NULL, 0);
     g_return_val_if_fail(plc->plc_read != NULL, 0);
 
+    old_len = playlist_get_length(playlist);
     plc->plc_read(filename, pos);
+    new_len = playlist_get_length(playlist);
 
     playlist_generate_shuffle_list(playlist);
     playlistwin_update_list(playlist);
 
-    return 1;
+    return new_len - old_len;
 }
 
 GList *
--- a/src/audacious/plugin.h	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/plugin.h	Sun Aug 12 20:03:43 2007 +0300
@@ -319,7 +319,7 @@
 G_BEGIN_DECLS
 
 /* So that input plugins can get the title formatting information */
-G_CONST_RETURN gchar * xmms_get_gentitle_format(void);
+G_CONST_RETURN gchar * get_gentitle_format(void);
 
 /* So that output plugins can communicate with effect plugins */
 EffectPlugin *get_current_effect_plugin(void);
@@ -329,5 +329,6 @@
 G_END_DECLS
 
 #include "audacious/mime.h"
+#include "audacious/custom_uri.h"
 
 #endif
--- a/src/audacious/tuple.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/tuple.c	Sun Aug 12 20:03:43 2007 +0300
@@ -123,11 +123,13 @@
 
     g_return_val_if_fail(tuple != NULL, FALSE);
     g_return_val_if_fail(field != NULL, FALSE);
-    g_return_val_if_fail(string != NULL, FALSE);
 
     if (mowgli_dictionary_find(tuple->dict, field))
         tuple_disassociate(tuple, field);
 
+    if (string == NULL)
+        return TRUE;
+
     value = mowgli_heap_alloc(tuple_value_heap);
     value->type = TUPLE_STRING;
     value->value.string = g_strdup(string);
--- a/src/audacious/tuple.h	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/tuple.h	Sun Aug 12 20:03:43 2007 +0300
@@ -41,5 +41,6 @@
 TupleValueType tuple_get_value_type(Tuple *tuple, const gchar *field);
 const gchar *tuple_get_string(Tuple *tuple, const gchar *field);
 int tuple_get_int(Tuple *tuple, const gchar *field);
+#define tuple_free(x) mowgli_object_unref(x);
 
 #endif
--- a/src/audacious/tuple_formatter.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/tuple_formatter.c	Sun Aug 12 20:03:43 2007 +0300
@@ -25,6 +25,14 @@
 #include "tuple.h"
 #include "tuple_formatter.h"
 
+#define _DEBUG
+
+#ifdef _DEBUG
+# define _TRACE(fmt, ...) g_print("[tuple-fmt] %s(%d) " fmt "\n", __FILE__, __LINE__, __VA_ARGS__);
+#else
+# define _TRACE(fmt, ...)
+#endif
+
 /*
  * the tuple formatter:
  *
@@ -72,14 +80,19 @@
     ctx = g_new0(TupleFormatterContext, 1);
     ctx->str = g_string_new("");
 
+    _TRACE("parsing <%s>", string);
+
     /* parsers are ugly */
     for (iter = string; *iter != '\0'; iter++)
     {
         /* if it's raw text, just copy the byte */
-        if (*iter != '$' && *iter != '%' && (*iter != '}' || (*iter == '}' && level > 0)))
+        if (*iter != '$' && *iter != '%' && *iter != '}' )
+        {
+            g_string_append_c(ctx->str, *iter);
+        }
+        else if (*iter == '}' && level > 0)
         {
             level--;
-            g_string_append_c(ctx->str, *iter);
         }
         else if (g_str_has_prefix(iter, "${") == TRUE)
         {
@@ -87,13 +100,12 @@
             GString *argument = g_string_new("");
             GString *sel = expression;
             gchar *result;
-            gboolean rewind = FALSE;
+            level++;
 
             for (iter += 2; *iter != '\0'; iter++)
             {
                 if (*iter == ':')
                 {
-		    level++;
                     if (sel != argument)
                     {
                         sel = argument;
@@ -115,12 +127,10 @@
                 else if (*iter == '}' && (sel == argument))
                 {
                     level--;
-                    if (level + 1 > 0)
-                    {
-                        iter++;
-                        rewind = *(iter - 1) == '}' && *iter != '}';
-                        break;
-                    }
+                    if (level == 0)
+                      break;
+                    else
+                      g_string_append_c(sel, *iter);
                 }
                 else if (*iter == '}' && ((sel != argument)))
                     break;
@@ -147,9 +157,6 @@
 
             if (*iter == '\0')
                 break;
-
-            if (rewind)
-                iter--;
         }
         else if (g_str_has_prefix(iter, "%{") == TRUE)
         {
@@ -157,14 +164,19 @@
             GString *argument = g_string_new("");
             GString *sel = expression;
             gchar *result;
-            gboolean rewind = FALSE;
+            level++;
 
             for (iter += 2; *iter != '\0'; iter++)
             {
                 if (*iter == ':')
                 {
-		    level++;
-                    sel = argument;
+                    if (sel != argument)
+                    {
+                        sel = argument;
+                        continue;
+                    }
+                    else
+                        g_string_append_c(sel, *iter);
                     continue;
                 }
 
@@ -179,12 +191,10 @@
                 else if (*iter == '}' && (sel == argument))
                 {
                     level--;
-                    if (level + 1 > 0)
-                    {
-                        iter++;
-                        rewind = *(iter - 1) == '}' && *iter != '}';
-                        break;
-                    }
+                    if (level == 0)
+                      break;
+                    else
+                    g_string_append_c(sel, *iter);
                 }
                 else if (*iter == '}' && ((sel != argument)))
                     break;
@@ -211,9 +221,6 @@
 
             if (*iter == '\0')
                 break;
-
-            if (rewind)
-                iter--;
         }
     }
 
@@ -221,6 +228,8 @@
     g_string_free(ctx->str, TRUE);
     g_free(ctx);
 
+    _TRACE("parsed <%s> as <%s>", string, out);
+
     return out;
 }
 
@@ -371,35 +380,64 @@
     return (tuple_get_value_type(tuple, expression) != TUPLE_UNKNOWN) ? TRUE : FALSE;
 }
 
-/* builtin-keyword: ${==arg1,arg2}, returns TRUE if <arg1> and <arg2> match. */
+/* builtin-keyword: ${==arg1,arg2}, returns TRUE if <arg1> and <arg2> match.
+   <arg1> and <arg2> can also be raw text, which should be enclosed in "double quotes". */
 static gboolean
 tuple_formatter_expression_match(Tuple *tuple, const gchar *expression)
 {
     gchar **args = g_strsplit(expression, ",", 2);
-    gchar *arg1, *arg2;
+    gchar *arg1 = NULL, *arg2 = NULL;
     gint ret;
 
-    if (tuple_get_value_type(tuple, args[0]) == TUPLE_UNKNOWN)
+    if (args[0][0] == '\"') /* check if arg1 is "raw text" */
+    {
+        if ( strlen(args[0]) > 1 )
+        {
+            args[0][strlen(args[0]) - 1] = '\0';
+            arg1 = g_strdup(&(args[0][1]));
+            args[0][strlen(args[0]) - 1] = '\"';
+        }
+        else /* bad formatted arg */
+            return FALSE;
+    }
+    else if (tuple_get_value_type(tuple, args[0]) == TUPLE_UNKNOWN)
+    {
+        g_strfreev(args);
+        return FALSE;
+    }
+    
+    if (args[1][0] == '\"') /* check if arg2 is "raw text" */
+    {
+        if ( strlen(args[1]) > 1 )
+        {
+            args[1][strlen(args[1]) - 1] = '\0';
+            arg2 = g_strdup(&(args[1][1]));
+            args[1][strlen(args[1]) - 1] = '\"';
+        }
+        else /* bad formatted arg */
+            return FALSE;
+    }
+    else if (tuple_get_value_type(tuple, args[1]) == TUPLE_UNKNOWN)
     {
         g_strfreev(args);
         return FALSE;
     }
 
-    if (tuple_get_value_type(tuple, args[1]) == TUPLE_UNKNOWN)
+    if (!arg1) /* if arg1 is not "raw text", get the tuple value */
     {
-        g_strfreev(args);
-        return FALSE;
+        if (tuple_get_value_type(tuple, args[0]) == TUPLE_STRING)
+            arg1 = g_strdup(tuple_get_string(tuple, args[0]));
+        else
+            arg1 = g_strdup_printf("%d", tuple_get_int(tuple, args[0]));
     }
 
-    if (tuple_get_value_type(tuple, args[0]) == TUPLE_STRING)
-        arg1 = g_strdup(tuple_get_string(tuple, args[0]));
-    else
-        arg1 = g_strdup_printf("%d", tuple_get_int(tuple, args[0]));
-
-    if (tuple_get_value_type(tuple, args[1]) == TUPLE_STRING)
-        arg2 = g_strdup(tuple_get_string(tuple, args[1]));
-    else
-        arg2 = g_strdup_printf("%d", tuple_get_int(tuple, args[1]));
+    if (!arg2) /* if arg2 is not "raw text", get the tuple value */
+    {
+        if (tuple_get_value_type(tuple, args[1]) == TUPLE_STRING)
+            arg2 = g_strdup(tuple_get_string(tuple, args[1]));
+        else
+            arg2 = g_strdup_printf("%d", tuple_get_int(tuple, args[1]));
+    }
 
     ret = g_ascii_strcasecmp(arg1, arg2);
     g_free(arg1);
@@ -409,7 +447,8 @@
     return ret ? FALSE : TRUE;
 }
 
-/* builtin-keyword: ${!=arg1,arg2}. returns TRUE if <arg1> and <arg2> don't match. */
+/* builtin-keyword: ${!=arg1,arg2}. returns TRUE if <arg1> and <arg2> don't match.
+   <arg1> and <arg2> can also be raw text, which should be enclosed in "double quotes". */
 static gboolean
 tuple_formatter_expression_nonmatch(Tuple *tuple, const gchar *expression)
 {
--- a/src/audacious/ui_skinned_horizontal_slider.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/ui_skinned_horizontal_slider.c	Sun Aug 12 20:03:43 2007 +0300
@@ -219,10 +219,11 @@
     widget->allocation = *allocation;
     widget->allocation.x *= (1+priv->double_size);
     widget->allocation.y *= (1+priv->double_size);
+
     if (priv->knob_height == priv->height)
-        priv->knob_height = allocation->height;
-    priv->width = allocation->width;
-    priv->height = allocation->height;
+        priv->knob_height = allocation->height/(priv->double_size ? 2 : 1);
+    priv->width = allocation->width/(priv->double_size ? 2 : 1);
+    priv->height = allocation->height/(priv->double_size ? 2 : 1);
 
     if (GTK_WIDGET_REALIZED (widget))
         gdk_window_move_resize(widget->window, widget->allocation.x, widget->allocation.y, allocation->width, allocation->height);
--- a/src/audacious/ui_skinned_playlist.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/audacious/ui_skinned_playlist.c	Sun Aug 12 20:03:43 2007 +0300
@@ -923,7 +923,7 @@
             playlistwin_update_list(playlist_get_active());
         }
         priv->drag_pos = nr;
-    } else {
+    } else if (cfg.show_filepopup_for_tuple) {
         gint pos = ui_skinned_playlist_get_position(widget, event->x, event->y);
         gint cur_pos = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "popup_position"));
         if (pos != cur_pos) {
--- a/src/tests/tuple_formatter_test.c	Sat Aug 11 01:49:26 2007 +0300
+++ b/src/tests/tuple_formatter_test.c	Sun Aug 12 20:03:43 2007 +0300
@@ -130,6 +130,56 @@
     }
     g_free(tstr);
 
+    tuple_associate_string(tuple, "sheep", "");
+
+    tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${?sheep:${sheep} - }${splork}");
+    if (g_ascii_strcasecmp(tstr, "moo -  - moo"))
+    {
+        g_print("fail 13: '%s'\n", tstr);
+        return EXIT_FAILURE;
+    }
+    g_free(tstr);
+
+    tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${?sheep:${sheep} - }${splork}");
+    if (g_ascii_strcasecmp(tstr, "moo -  - moo"))
+    {
+        g_print("fail 14: '%s'\n", tstr);
+        return EXIT_FAILURE;
+    }
+    g_free(tstr);
+
+    tstr = tuple_formatter_process_string(tuple, "${==splork,\"moo\":const text field matches}");
+    if (g_ascii_strcasecmp(tstr, "const text field matches"))
+    {
+        g_print("fail 15: '%s'\n", tstr);
+        return EXIT_FAILURE;
+    }
+    g_free(tstr);
+
+    tstr = tuple_formatter_process_string(tuple, "${==\"moo\",\"moo\":const text fields match}");
+    if (g_ascii_strcasecmp(tstr, "const text fields match"))
+    {
+        g_print("fail 16: '%s'\n", tstr);
+        return EXIT_FAILURE;
+    }
+    g_free(tstr);
+
+    tstr = tuple_formatter_process_string(tuple, "${!=splork,\"muu\":const text field doesn't match}");
+    if (g_ascii_strcasecmp(tstr, "const text field doesn't match"))
+    {
+        g_print("fail 17: '%s'\n", tstr);
+        return EXIT_FAILURE;
+    }
+    g_free(tstr);
+
+    tstr = tuple_formatter_process_string(tuple, "${!=\"moo\",\"muu\":const text fields do not match}");
+    if (g_ascii_strcasecmp(tstr, "const text fields do not match"))
+    {
+        g_print("fail 18: '%s'\n", tstr);
+        return EXIT_FAILURE;
+    }
+    g_free(tstr);
+
     mowgli_object_unref(tuple);
 
     return EXIT_SUCCESS;