changeset 1502:45e2325fd07f

Automated merge with ssh://hg.atheme.org//hg/audacious-plugins
author William Pitcock <nenolod@atheme-project.org>
date Fri, 17 Aug 2007 11:58:12 -0500
parents 04f8c7624ea3 (current diff) 611d8db6b421 (diff)
children d0e39fd56c78 acd3b3d8d2cb
files
diffstat 10 files changed, 554 insertions(+), 123 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Fri Aug 17 11:40:30 2007 -0500
+++ b/configure.ac	Fri Aug 17 11:58:12 2007 -0500
@@ -1234,7 +1234,7 @@
 dnl *** MTP Upload
 
 AC_ARG_ENABLE(mtp_up,
-[  --enable-mtp_up           enable mtp upload support. (default=disabled)],
+[  --enable-mtp_up           enable mtp upload support. (default=enabled)],
 [have_mtp_up=$enableval],
 [have_mtp_up=no])
 
--- a/src/cdaudio-ng/cdaudio-ng.c	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/cdaudio-ng/cdaudio-ng.c	Fri Aug 17 11:58:12 2007 -0500
@@ -1,3 +1,21 @@
+/*
+ * Audacious CD Digital Audio plugin
+ *
+ * Copyright (c) 2007 Calin Crisan <ccrisan@gmail.com>
+ * 
+ * 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>.
+ */
+
 
 #include <string.h>
 #include <stdlib.h>
@@ -21,6 +39,8 @@
 #include <audacious/plugin.h>
 #include <audacious/util.h>
 #include <audacious/output.h>
+#include <audacious/ui_plugin_menu.h>
+#include <audacious/playlist.h>
 #include "config.h"
 
 #include "cdaudio-ng.h"
@@ -44,6 +64,7 @@
 static char				cddb_server[DEF_STRING_LEN];
 static int				cddb_port;
 static InputPlayback	*pglobalinputplayback = NULL;
+static GtkWidget		*main_menu_item, *playlist_menu_item;
 
 static void				cdaudio_init();
 static void				cdaudio_about();
@@ -61,6 +82,7 @@
 static void				cdaudio_get_song_info(gchar *filename, gchar **title, gint *length);
 static Tuple			*cdaudio_get_song_tuple(gchar *filename);
 
+static void				menu_click();
 static Tuple			*create_tuple_from_trackinfo(char *filename);
 static void				dae_play_loop(dae_params_t *pdae_params);
 static int				calculate_track_length(int startlsn, int endlsn);
@@ -147,6 +169,18 @@
 
 	configure_set_variables(/*&use_dae, */&limitspeed, &use_cdtext, &use_cddb, device, &debug, cddb_server, &cddb_port);
 	configure_create_gui();
+
+	main_menu_item = gtk_image_menu_item_new_with_label(MENU_ITEM_TEXT);
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(main_menu_item), gtk_image_new_from_stock(GTK_STOCK_CDROM, GTK_ICON_SIZE_MENU));
+	gtk_widget_show(main_menu_item);
+	audacious_menu_plugin_item_add(AUDACIOUS_MENU_MAIN, main_menu_item);
+	g_signal_connect(G_OBJECT(main_menu_item), "button_press_event", G_CALLBACK(menu_click), NULL);  
+	
+	playlist_menu_item = gtk_image_menu_item_new_with_label(MENU_ITEM_TEXT);
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(playlist_menu_item), gtk_image_new_from_stock(GTK_STOCK_CDROM, GTK_ICON_SIZE_MENU));
+	gtk_widget_show(playlist_menu_item);
+	audacious_menu_plugin_item_add(AUDACIOUS_MENU_PLAYLIST, playlist_menu_item);
+	g_signal_connect(G_OBJECT(playlist_menu_item), "button_press_event", G_CALLBACK(menu_click), NULL);  
 	
 	uri_set_plugin("cdda://", &inputplugin);
 }
@@ -756,6 +790,37 @@
 
 	/* auxiliar functions */
 
+void menu_click()
+{
+    GList *list, *node;
+    gchar *filename;
+	
+	if (!(list = cdaudio_scan_dir(CDDA_DEFAULT))) {
+	    const gchar *markup =
+	        N_("<b><big>No playable CD found.</big></b>\n\n"
+	           "No CD inserted, or inserted CD is not an audio CD.\n");
+
+	    GtkWidget *dialog =
+	        gtk_message_dialog_new_with_markup(NULL,
+	                                           GTK_DIALOG_DESTROY_WITH_PARENT,
+	                                           GTK_MESSAGE_ERROR,
+	                                           GTK_BUTTONS_OK,
+	                                           _(markup));
+	    gtk_dialog_run(GTK_DIALOG(dialog));
+	    gtk_widget_destroy(dialog);
+		return;
+	}
+
+	for (node = list; node; node = g_list_next(node)) {
+		filename = g_build_filename(CDDA_DEFAULT, node->data, NULL);
+		playlist_add(playlist_get_active(), filename);
+		g_free(filename);
+		g_free(node->data);
+	}
+
+	g_list_free(list);
+}
+
 Tuple *create_tuple_from_trackinfo(char *filename)
 {
 	if (trackinfo == NULL)
--- a/src/cdaudio-ng/cdaudio-ng.h	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/cdaudio-ng/cdaudio-ng.h	Fri Aug 17 11:58:12 2007 -0500
@@ -1,3 +1,21 @@
+/*
+ * Audacious CD Digital Audio plugin
+ *
+ * Copyright (c) 2007 Calin Crisan <ccrisan@gmail.com>
+ * 
+ * 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 theio
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses>.
+ */
+
 
 #ifndef CDAUDIO_NG_H
 #define CDAUDIO_NG_H
@@ -8,6 +26,7 @@
 #define CDDA_DAE_FRAMES				8
 #define CDDA_DEFAULT_CDDB_SERVER	"freedb.org"
 #define CDDA_DEFAULT_CDDB_PORT		888
+#define MENU_ITEM_TEXT				"Add CD"
 
 
 typedef struct {
--- a/src/console/Audacious_Config.cxx	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/console/Audacious_Config.cxx	Fri Aug 17 11:58:12 2007 -0500
@@ -26,11 +26,11 @@
 	bmp_cfg_db_get_int(db, "console", "loop_length", &audcfg.loop_length);
 	bmp_cfg_db_get_bool(db, "console", "resample", &audcfg.resample);
 	bmp_cfg_db_get_int(db, "console", "resample_rate", &audcfg.resample_rate);
-	bmp_cfg_db_get_bool(db, "console", "nsfe_playlist", &audcfg.nsfe_playlist);
 	bmp_cfg_db_get_int(db, "console", "treble", &audcfg.treble);
 	bmp_cfg_db_get_int(db, "console", "bass", &audcfg.bass);
 	bmp_cfg_db_get_bool(db, "console", "ignore_spc_length", &audcfg.ignore_spc_length);
 	bmp_cfg_db_get_int(db, "console", "echo", &audcfg.echo);
+	bmp_cfg_db_get_bool(db, "console", "inc_spc_reverb", &audcfg.inc_spc_reverb);
 	bmp_cfg_db_close(db);
 }
 
@@ -41,11 +41,11 @@
 	bmp_cfg_db_set_int(db, "console", "loop_length", audcfg.loop_length);
 	bmp_cfg_db_set_bool(db, "console", "resample", audcfg.resample);
 	bmp_cfg_db_set_int(db, "console", "resample_rate", audcfg.resample_rate);
-	bmp_cfg_db_set_bool(db, "console", "nsfe_playlist", audcfg.nsfe_playlist);
 	bmp_cfg_db_set_int(db, "console", "treble", audcfg.treble);
 	bmp_cfg_db_set_int(db, "console", "bass", audcfg.bass);
 	bmp_cfg_db_set_bool(db, "console", "ignore_spc_length", audcfg.ignore_spc_length);
 	bmp_cfg_db_set_int(db, "console", "echo", audcfg.echo);
+	bmp_cfg_db_set_bool(db, "console", "inc_spc_reverb", audcfg.inc_spc_reverb);
 	bmp_cfg_db_close(db);
 }
 
@@ -77,16 +77,16 @@
   audcfg.loop_length = (gint)gtk_spin_button_get_value( GTK_SPIN_BUTTON(spbt) );
 }
 
-static void i_cfg_ev_nsfeoptpl_enable_commit( gpointer cbt )
-{
-  audcfg.nsfe_playlist = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(cbt) );
-}
-
 static void i_cfg_ev_ignorespclen_enable_commit( gpointer cbt )
 {
   audcfg.ignore_spc_length = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(cbt) );
 }
 
+static void i_cfg_ev_incspcreverb_enable_commit( gpointer cbt )
+{
+  audcfg.inc_spc_reverb = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(cbt) );
+}
+
 static void i_cfg_ev_bok( gpointer configwin )
 {
   console_cfg_save();
@@ -104,7 +104,7 @@
 {
 	static GtkWidget *configwin = NULL;
 	GtkWidget *configwin_vbox;
-	GtkWidget *configwin_gen_vbox, *configwin_nsf_vbox, *configwin_spc_vbox;
+	GtkWidget *configwin_gen_vbox, *configwin_spc_vbox;
 	GtkWidget *configwin_gen_resample_frame, *configwin_gen_resample_vbox;
 	GtkWidget *configwin_gen_resample_cbt, *configwin_gen_resample_val_hbox;
 	GtkWidget *configwin_gen_resample_val_spbt;
@@ -113,8 +113,7 @@
 	GtkWidget *configwin_gen_playback_tb_bass_hbox, *configwin_gen_playback_tb_bass_spbt;
 	GtkWidget *configwin_gen_playback_tb_treble_hbox, *configwin_gen_playback_tb_treble_spbt;
 	GtkWidget *configwin_gen_playback_deflen_hbox, *configwin_gen_playback_deflen_spbt;
-	GtkWidget *configwin_nsf_nsfeoptpl_cbt;
-	GtkWidget *configwin_spc_ignorespclen_cbt;
+	GtkWidget *configwin_spc_ignorespclen_cbt, *configwin_spc_increverb_cbt;
 	GtkWidget /* *hseparator, */ *hbuttonbox, *button_ok, *button_cancel;
 	GtkWidget *configwin_notebook;
 	GtkTooltips *tips;
@@ -230,17 +229,6 @@
 		G_CALLBACK(i_cfg_ev_toggle_resample) , configwin_gen_resample_val_hbox );
 	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(configwin_gen_resample_cbt) , audcfg.resample );
 
-	// NSF/NSFE PAGE
-	configwin_nsf_vbox = gtk_vbox_new( FALSE , 3 );
-	gtk_container_set_border_width( GTK_CONTAINER(configwin_nsf_vbox), 5 );
-	gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) ,
-		configwin_nsf_vbox , gtk_label_new( _("NSF/NSFE") ) );
-	configwin_nsf_nsfeoptpl_cbt = gtk_check_button_new_with_label( _("Use optional NSFE playlist") );
-	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(configwin_nsf_nsfeoptpl_cbt) , audcfg.nsfe_playlist );
-	g_signal_connect_swapped( G_OBJECT(button_ok) , "clicked" ,
-		G_CALLBACK(i_cfg_ev_nsfeoptpl_enable_commit) , configwin_nsf_nsfeoptpl_cbt );
-	gtk_box_pack_start( GTK_BOX(configwin_nsf_vbox) ,
-		configwin_nsf_nsfeoptpl_cbt , FALSE , FALSE , 0 );
 
 	// SPC PAGE
 	configwin_spc_vbox = gtk_vbox_new( FALSE , 3 );
@@ -248,11 +236,17 @@
 	gtk_notebook_append_page( GTK_NOTEBOOK(configwin_notebook) ,
 		configwin_spc_vbox , gtk_label_new( _("SPC") ) );
 	configwin_spc_ignorespclen_cbt = gtk_check_button_new_with_label( _("Ignore length from SPC tags") );
+	configwin_spc_increverb_cbt = gtk_check_button_new_with_label( _("Increase reverb") );
 	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(configwin_spc_ignorespclen_cbt) , audcfg.ignore_spc_length );
+	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(configwin_spc_increverb_cbt) , audcfg.inc_spc_reverb );
 	g_signal_connect_swapped( G_OBJECT(button_ok) , "clicked" ,
 		G_CALLBACK(i_cfg_ev_ignorespclen_enable_commit) , configwin_spc_ignorespclen_cbt );
+	g_signal_connect_swapped( G_OBJECT(button_ok) , "clicked" ,
+		G_CALLBACK(i_cfg_ev_incspcreverb_enable_commit) , configwin_spc_increverb_cbt );
 	gtk_box_pack_start( GTK_BOX(configwin_spc_vbox) ,
 		configwin_spc_ignorespclen_cbt , FALSE , FALSE , 0 );
+	gtk_box_pack_start( GTK_BOX(configwin_spc_vbox) ,
+		configwin_spc_increverb_cbt , FALSE , FALSE , 0 );
 
 	// horizontal separator and buttons
 	hbuttonbox = gtk_hbutton_box_new();
--- a/src/console/Audacious_Config.h	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/console/Audacious_Config.h	Fri Aug 17 11:58:12 2007 -0500
@@ -17,11 +17,11 @@
 	gint loop_length;   // length of tracks that lack timing information
 	gboolean resample;  // whether or not to resample
 	gint resample_rate; // rate to resample at
-	gboolean nsfe_playlist; // TODO: remove (nsfe playlist is now always enabled)
 	gint treble; // -100 to +100
 	gint bass;   // -100 to +100
 	gboolean ignore_spc_length; // if true, ignore length from SPC tags
 	gint echo;   // 0 to +100
+	gboolean inc_spc_reverb; // if true, increases the default reverb
 }
 AudaciousConsoleConfig;
 
--- a/src/console/Audacious_Driver.cxx	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/console/Audacious_Driver.cxx	Fri Aug 17 11:58:12 2007 -0500
@@ -35,7 +35,8 @@
 int const fade_length    = 8 * 1000;
 int const path_max = 4096;
 
-AudaciousConsoleConfig audcfg = { 180, FALSE, 32000, TRUE, 0, 0, FALSE, 0 };
+AudaciousConsoleConfig audcfg =
+{ 180, FALSE, 32000, 0, 0, FALSE, 0, FALSE };
 static GThread* decode_thread;
 static GStaticMutex playback_mutex = G_STATIC_MUTEX_INIT;
 static int console_ip_is_going;
--- a/src/console/Spc_Dsp.cxx	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/console/Spc_Dsp.cxx	Fri Aug 17 11:58:12 2007 -0500
@@ -1,5 +1,8 @@
 // snes_spc 0.9.0. http://www.slack.net/~ant/
 
+// TODO: we can remove this as soon as the reverb problem is fixed. -- mf0102
+#include "Audacious_Config.h"
+
 #include "Spc_Dsp.h"
 
 #include "blargg_endian.h"
@@ -589,8 +592,9 @@
 		// Echo out
 		if ( !(REG(flg) & 0x20) )
 		{
-			int l = (echo_out_l >> 7) + ((echo_in_l * (int8_t) REG(efb)) >> 16);
-			int r = (echo_out_r >> 7) + ((echo_in_r * (int8_t) REG(efb)) >> 16);
+			unsigned shift = audcfg.inc_spc_reverb ? 14 : 16;
+			int l = (echo_out_l >> 7) + ((echo_in_l * (int8_t) REG(efb)) >> shift);
+			int r = (echo_out_r >> 7) + ((echo_in_r * (int8_t) REG(efb)) >> shift);
 			
 			// just to help pass more validation tests
 			#if SPC_MORE_ACCURACY
--- a/src/daap/daap.c	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/daap/daap.c	Fri Aug 17 11:58:12 2007 -0500
@@ -18,17 +18,44 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include <glib.h>
+
 #include <audacious/vfs.h>
 #include <audacious/plugin.h>
 #include <audacious/discovery.h>
-/*
-#include <audacious/configdb.h>
-#include <libmowgli/mowgli.h>
-#include <curl/curl.h>
-*/
-#include <glib.h>
+
+#include "xmms2-daap/daap_cmd.h"
+#include "xmms2-daap/daap_util.h"
 #include "xmms2-daap/daap_mdns_browse.h"
-#include "xmms2-daap/daap_cmd.h"
+#define DEFAULT_DAAP_PORT 3689
+#define DEBUG 1
+typedef struct {
+    gchar *host;
+    guint port;
+
+    GIOChannel *channel;
+
+} daap_data_t;
+
+typedef struct {
+    gboolean logged_in;
+    guint session_id;
+    guint revision_id;
+    guint request_id;
+} daap_login_data_t;
+
+typedef struct{
+    daap_data_t *daap_data;
+    gchar *url;
+    int fd;
+    guint pos;
+    gulong length; 
+}
+daap_handle_t;
+
+
+
+static GHashTable *login_sessions = NULL;
 
 gboolean daap_initialized=FALSE;
 
@@ -40,10 +67,197 @@
 
 guint request_id=0;
 
-GList * daap_get_server_playlist(gchar * host, gint port  )
+
+
+    static gboolean
+get_data_from_url (const gchar *url, gchar **host, guint *port, gchar **cmd)
+{
+    const gchar *port_ptr, *cmd_ptr, *end_ptr, *stripped;
+
+    stripped = url + sizeof (gchar) * strlen ("daap://");
+
+    end_ptr = stripped + sizeof (gchar) * strlen (stripped);
+
+    if (stripped == end_ptr) {
+        g_print("DAAP: Empty URL\n");
+        return FALSE;
+    }
+
+    port_ptr = strstr (stripped, ":");
+    if (port && port_ptr && (port_ptr + 1) != end_ptr) {
+        *port = strtol (port_ptr + 1, (gchar **) NULL, 10);
+        if (*port == 0) {
+            *port = DEFAULT_DAAP_PORT;
+        }
+    } else if (port) {
+        *port = DEFAULT_DAAP_PORT;
+    }
+
+    cmd_ptr = strstr (stripped, "/");
+    if (cmd && cmd_ptr && (cmd_ptr + 1) != end_ptr) {
+        *cmd = g_strdup (cmd_ptr);
+    } else if (cmd) {
+        /* cmd wanted but not found */
+        g_print("DAAP: No file requested\n");
+    } else if (!cmd && cmd_ptr && (cmd_ptr + 1) != end_ptr) {
+        /* cmd not wanted but found */
+        g_print("DAAP: No such directory\n");
+        return FALSE;
+    }
+
+    if (port_ptr) {
+        *host = g_strndup (stripped, port_ptr - stripped);
+    } else if (cmd_ptr) {
+        *host = g_strndup (stripped, cmd_ptr - stripped);
+    } else {
+        *host = g_strdup (stripped);
+    }
+
+    return TRUE;
+}
+
+
+
+    static gboolean
+daap_init (daap_handle_t *handle)
 {
-return NULL;
+    gint dbid;
+    GSList *dbid_list = NULL;
+    daap_data_t *data;
+    daap_login_data_t *login_data;
+    guint filesize;
+    gchar *command=NULL;
+    gchar *hash;
+
+    data = g_new0 (daap_data_t, 1);
+
+    if (!get_data_from_url (handle->url, &(data->host), &(data->port), &command))
+        return FALSE;
+
+    hash = g_strdup_printf ("%s:%u", data->host, data->port);
+
+    login_data = g_hash_table_lookup (login_sessions, hash);
+    if (!login_data) 
+    {
+#if DEBUG
+        g_print ("creating login data for %s\n", hash);
+#endif
+        login_data = g_new0 (daap_login_data_t, 1);
+
+        login_data->request_id = 1;
+        login_data->logged_in = TRUE;
+
+        login_data->session_id = daap_command_login (data->host, data->port,
+                login_data->request_id);
+        if(login_data->session_id==0)
+            return FALSE;
+
+        g_hash_table_insert (login_sessions, hash, login_data);
+    }
+
+    login_data->revision_id = daap_command_update (data->host, data->port,
+            login_data->session_id,
+            login_data->request_id);
+    dbid_list = daap_command_db_list (data->host, data->port,
+            login_data->session_id,
+            login_data->revision_id,
+            login_data->request_id);
+    if (!dbid_list) {
+        return FALSE;
+    }
+
+    /* XXX: see XXX in the browse function above */
+    dbid = ((cc_item_record_t *) dbid_list->data)->dbid;
+    /* want to request a stream, but don't read the data yet */
+    data->channel = daap_command_init_stream (data->host, data->port,
+            login_data->session_id,
+            login_data->revision_id,
+            login_data->request_id, dbid,
+            command,&filesize);
+    if (!data->channel) {
+        return FALSE;
+    }
+
+    login_data->request_id++;
+    
+    handle->daap_data=data;
+    handle->length=filesize;
+    handle->pos=0;
+    g_slist_foreach (dbid_list, (GFunc) cc_item_record_free, NULL);
+    g_slist_free (dbid_list);
+    g_free (command);
+
+    return TRUE;
+}
 
+
+
+
+
+
+
+    GList*
+daap_get_tracks_from_server (gchar *host, guint port)
+{
+    GList * output=NULL;
+    GSList *dbid_list = NULL;
+    GSList *song_list = NULL, *song_el;
+    cc_item_record_t *db_data;
+    daap_login_data_t *login_data;
+    gchar *hash;
+
+    hash = g_strdup_printf ("%s:%u", host, port);
+
+    login_data = g_hash_table_lookup (login_sessions, hash);
+
+    if (!login_data) {
+        login_data = g_new0 (daap_login_data_t, 1);
+
+        login_data->session_id = daap_command_login (host, port, 0);
+
+        login_data->revision_id = daap_command_update (host, port,
+                login_data->session_id,
+                0);
+
+        login_data->request_id = 1;
+        login_data->logged_in = TRUE;
+
+        g_hash_table_insert (login_sessions, hash, login_data);
+    } else {
+        login_data->revision_id = daap_command_update (host, port,
+                login_data->session_id,
+                0);
+    }
+
+    dbid_list = daap_command_db_list (host, port, login_data->session_id,
+            login_data->revision_id, 0);
+    if (!dbid_list) {
+        return NULL;
+    }
+
+    /* XXX i've never seen more than one db per server out in the wild,
+     *     let's hope that never changes *wink*
+     *     just use the first db in the list */
+    db_data = (cc_item_record_t *) dbid_list->data;
+    song_list = daap_command_song_list (host, port, login_data->session_id,
+            login_data->revision_id,
+            0, db_data->dbid);
+
+    g_slist_foreach (dbid_list, (GFunc) cc_item_record_free, NULL);
+    g_slist_free (dbid_list);
+
+    if (!song_list) {
+        return NULL;
+    }
+
+    for (song_el = song_list; song_el; song_el = g_slist_next (song_el)) 
+        output=g_list_prepend(output, g_memdup(song_el->data,sizeof(cc_item_record_t)));
+
+
+    g_slist_foreach (song_list, (GFunc) cc_item_record_free, NULL);
+    g_slist_free (song_list);
+
+    return g_list_reverse(output);
 }
 
 
@@ -52,7 +266,7 @@
     discovery_device_t * current_device=NULL;
     GList * returned_devices=NULL;
     GSList * daap_found_devices=NULL,
-          * current_server=NULL;
+           * current_server=NULL;
 
     if(mutex_discovery==NULL)
         return NULL;
@@ -61,23 +275,13 @@
     g_print ("caut\n");
     daap_found_devices  = daap_mdns_get_server_list ();
     current_server=daap_found_devices;
-    g_print ("entering for\n");
-    if(current_server!=NULL)
-        g_print("!=NULL\n");
-    else 
-        g_print("==NULL\n");
-        
+
     for (; current_server; current_server = g_slist_next (current_server)) 
     {
-     g_print ("in for\n");
-
         current_device = g_new0(discovery_device_t,1);
         daap_mdns_server_t *serv=current_server->data;
         current_device->device_name = 
-            g_strdup_printf("%s(%s)",
-                    serv->server_name,
-                    serv->mdns_hostname
-                    );
+            g_strdup_printf("%s(%s)",serv->server_name, serv->mdns_hostname);
 
         current_device->device_address = 
             g_strdup_printf(
@@ -86,16 +290,15 @@
                     serv->port
                     );
         current_device->device_playlist=
-            daap_get_server_playlist(
+            daap_get_tracks_from_server(
                     serv->mdns_hostname,
                     serv->port
                     );
         returned_devices = g_list_prepend(returned_devices,current_device); 
-#if 1
+#if DEBUG
         g_print("DAAP: Found device %s at address %s\n", current_device->device_name ,current_device->device_address );
 #endif
     }
-    g_print("am iesit\n");
     g_slist_free(daap_found_devices);
     g_mutex_unlock(mutex_discovery);
     return g_list_reverse(returned_devices);
@@ -107,48 +310,72 @@
 VFSFile * daap_vfs_fopen_impl(const gchar * path, const gchar * mode)
 {
     VFSFile *file=NULL;
-    if(!mutex_init)
+    daap_handle_t *handle = g_new0(daap_handle_t, 1);
+    handle->url=g_strdup(path);
+
+    if (!path || !mode)
         return NULL;
 
-    g_mutex_lock(mutex_init); /* locking for init */
-    if(!daap_initialized)
+    if( !daap_init(handle) )
     {
-        if( !daap_mdns_initialize ())
-        {
-#if 1    /*this isn't a fatal error, we can try again later*/
-            g_print("Error while initializing DAAP !!!\n");
+#if DEBUG    /*this isn't a fatal error, we can try again later*/
+        g_print("Error while initializing DAAP !!!\n");
 #endif          
-            g_mutex_unlock(mutex_init);
-            return NULL;
-        }
-        else
-        {
-#if 1   
-            g_print("DAAP was initialized succesfully\n");
+        return NULL;
+    }
+#if DEBUG   
+    g_print("DAAP was initialized succesfully\n");
 #endif  
-            daap_initialized=TRUE;
-        }
-    
-    if(daap_initialized)
+    file=g_new0(VFSFile, 1);
+    handle->fd=g_io_channel_unix_get_fd(handle->daap_data->channel);
+
+    if (handle->fd < 0) 
     {
-        sleep(1);
-        daap_discovery_get_devices_impl();
-    }
-    }
-    g_mutex_unlock(mutex_init);  /*init ended*/
-
-    file = g_new0(VFSFile, 1);
-//    GList * l = 
-
-        return file;
+        g_print("vfs_fopen got a negative FD \n");
+        g_free(file);
+        file = NULL;
+    } 
+    else 
+        file->handle=(void*)handle;
+    return file;
 }
 
 gint daap_vfs_fclose_impl(VFSFile * file)
 {
-    return 0;
+    gint ret=0;
+    daap_handle_t * handle = (daap_handle_t *)file->handle;
+    if (file == NULL)
+        return -1;
+
+    if (file->handle)
+    {
+        if(g_io_channel_shutdown(handle->daap_data->channel,TRUE,NULL)!=G_IO_STATUS_NORMAL) 
+            ret = -1;
+        else
+            {
+                g_io_channel_unref(handle->daap_data->channel);
+                ret=0;
+            }
+        g_free(file->handle);
+        file->handle=NULL;
+    }
+    return ret;
+
+return -1;
 }
+
 size_t daap_vfs_fread_impl(gpointer ptr, size_t size, size_t nmemb, VFSFile * file)
 {
+    daap_handle_t *handle= (daap_handle_t *)file->handle;
+    size_t ret=0;
+if (file == NULL)
+        return 0;
+if( g_io_channel_read_chars (handle->daap_data->channel,ptr,size*nmemb,&ret,NULL)==G_IO_STATUS_NORMAL)
+    {
+        handle->pos+=(size*nmemb);
+        return ret;
+    }
+else 
     return 0;
 }
 
@@ -157,33 +384,50 @@
     return -1;
 }
 
-gint daap_vfs_getc_impl(VFSFile * stream)
+gint daap_vfs_getc_impl(VFSFile * file)
 {
-    return 0;
+guchar ret=EOF;
+daap_handle_t *handle = (daap_handle_t *)file->handle;
+int status=g_io_channel_read_chars (handle->daap_data->channel,(void*)&ret,1,NULL,NULL);
+if(status==G_IO_STATUS_NORMAL)
+    {
+    g_print ("fgetc OK\n");
+    handle->pos++;
+    return ret;
+    }
+else 
+{
+g_print ("fgetc failed\n");
+    return EOF;
+}
 }
 
-gint daap_vfs_ungetc_impl(gint c, VFSFile * stream)
-{
-    return 0;
-}
 gint daap_vfs_fseek_impl(VFSFile * file, glong offset, gint whence)
 {
     return -1;
 }
 
-void daap_vfs_rewind_impl(VFSFile * file)
+gint daap_vfs_ungetc_impl(gint c, VFSFile * stream)
+{
+return c;
+}
+
+void daap_vfs_rewind_impl(VFSFile * stream)
 {
     return;
 }
 
-glong daap_vfs_ftell_impl(VFSFile * file)
+glong daap_vfs_ftell_impl(VFSFile * stream)
 {
-    return 0;
+    daap_handle_t *handle=stream->handle;
+   return handle->pos;
 }
 
 gboolean daap_vfs_feof_impl(VFSFile * file)
 {
-    return 1;
+   daap_handle_t *handle=file->handle;
+  off_t at = daap_vfs_ftell_impl(file);
+  return (gboolean) (at >= handle->length) ? TRUE : FALSE;
 }
 
 gint daap_vfs_truncate_impl(VFSFile * file, glong size)
@@ -192,11 +436,29 @@
 }
 off_t daap_vfs_fsize_impl(VFSFile * file)
 {
-    return 0;
+return 0;
 }
+
 gchar *daap_vfs_metadata_impl(VFSFile * file, const gchar * field)
 {
+daap_handle_t *handle;
+g_print("Requested metadata: '%s' \n",field);
+
+if(file && file->handle)
+    handle = (daap_handle_t *)file->handle;
+else 
     return NULL;
+
+/*if (!g_ascii_strncasecmp(field, "stream-name", 11))
+    return handle->url;
+if (!g_ascii_strncasecmp(field, "track-name",10))
+    return handle->url;
+*/
+
+if (!g_ascii_strncasecmp(field, "content-type", 12))
+    return g_strdup("audio/mpeg");
+return NULL;
+
 }
 
 VFSConstructor daap_const = {
@@ -221,6 +483,11 @@
     mutex_init = g_mutex_new();        
     mutex_discovery = g_mutex_new();        
     vfs_register_transport(&daap_const);
+    daap_mdns_initialize ();
+    if (!login_sessions) 
+        login_sessions = g_hash_table_new (g_str_hash, g_str_equal);
+
+
 }
 static void cleanup(void)
 {
--- a/src/mtp_up/mtp.c	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/mtp_up/mtp.c	Fri Aug 17 11:58:12 2007 -0500
@@ -21,6 +21,10 @@
 #include <audacious/plugin.h>
 #include <audacious/playlist.h>
 #include <audacious/ui_plugin_menu.h>
+
+#include <gtk/gtk.h>
+#include <audacious/util.h>
+
 #define DEBUG 1
 
 #define DEFAULT_LABEL "Upload to MTP device"
@@ -34,7 +38,7 @@
 LIBMTP_file_t *filelist;
 Playlist *active_playlist;
 
-static gboolean plugin_active = FALSE;
+static gboolean plugin_active = FALSE,exiting=FALSE;
 
 void mtp_init ( void );
 void mtp_cleanup ( void );
@@ -56,10 +60,28 @@
 GeneralPlugin *mtp_gplist[] = { &mtp_gp, NULL };
 DECLARE_PLUGIN(mtp_gp, NULL, NULL, NULL, NULL, NULL, mtp_gplist, NULL, NULL)
 
+
+void show_dialog(const gchar* message)
+{
+    GDK_THREADS_ENTER();
+    GtkWidget *dialog = gtk_message_dialog_new (NULL,
+            GTK_DIALOG_MODAL,
+            GTK_MESSAGE_ERROR,
+            GTK_BUTTONS_OK,
+            message);
+    gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_show(dialog);
+    gtk_widget_destroy(dialog);
+    GDK_THREADS_LEAVE();
+
+}
+
+
 GList * get_upload_list()
 {
     Tuple *tuple;
-    gchar *from_path;
+    gchar *from_path,*filename;
+    VFSFile*f;
     GList *node=NULL,*up_list=NULL;
     PlaylistEntry *entry;
     Playlist *current_play = playlist_get_active();
@@ -73,11 +95,30 @@
         {
             tuple = entry->tuple;
             from_path = g_strdup_printf("%s/%s", tuple_get_string(tuple, "file-path"), tuple_get_string(tuple, "file-name"));
-            VFSFile* f = vfs_fopen(from_path,"r");
-            if(!vfs_is_streaming(f))
-                up_list=g_list_prepend(up_list,from_path);
-            vfs_fclose(f);
+            gchar *tmp;
+            tmp = g_strescape(from_path,NULL);
+            filename=g_filename_from_uri(tmp,NULL,NULL);
+
+            if(filename)
+            {
+                f = vfs_fopen(from_path,"r");
+                if(!vfs_is_streaming(f))
+
+
+                    up_list=g_list_prepend(up_list,filename);
+
+                g_free(tmp);
+                vfs_fclose(f);
+
+            }
+            else 
+            {
+                up_list = g_list_prepend(up_list,tmp);
+                g_free(filename);
+            }
+
             entry->selected = FALSE;
+            g_free(from_path);
         }
         node = g_list_next(node);
     }
@@ -85,7 +126,7 @@
     return g_list_reverse(up_list);
 }
 
-void upload_file(gchar *from_path)
+gint upload_file(gchar *from_path)
 {
     int ret;
     gchar *comp, *filename;
@@ -100,11 +141,14 @@
 #if DEBUG
         g_print("ERROR! encountered while stat()'ing \"%s\"\n",from_path);
 #endif
-        return;
+        return 1;
     }
     filesize = (uint64_t) sb.st_size;
     filename = g_path_get_basename(from_path);
-    parent_id = 0;
+    parent_id = mtp_device->default_music_folder;
+#if DEBUG 
+    g_print("Parent id : %d\n",parent_id); 
+#endif    
     genfile = LIBMTP_new_file_t();
     genfile->filesize = filesize;
     genfile->filename = strdup(filename);
@@ -112,49 +156,78 @@
     g_print("Uploading track '%s'\n",comp);
 #endif
     ret = LIBMTP_Send_File_From_File(mtp_device, comp , genfile, NULL , NULL, parent_id);
-#if DEBUG
     if (ret == 0) 
         g_print("Upload finished!\n");
     else
+    {
         g_print("An error has occured while uploading '%s'...\nUpload failed!!!",comp);
-#endif
+        mtp_initialised = FALSE;
+        return 1;
+    }
     LIBMTP_destroy_file_t(genfile);
+#if DEBUG 
+    g_print("genfile destroyed \n");    
+#endif    
     g_free(filename);
     g_free(comp);
+#if DEBUG
+    g_print("Free ok..exiting upload_file \n ");    
+#endif
+    return 0;
 }
 
 
 gpointer upload(gpointer arg)
 {
-    if(!mutex)
+     if(!mutex)
        {
-            gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))),DEFAULT_LABEL);
-            gtk_widget_set_sensitive(menuitem, TRUE);
-            return NULL;
-       }
-    g_mutex_lock(mutex);
+       gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))),DEFAULT_LABEL);
+       gtk_widget_set_sensitive(menuitem, TRUE);
+       return NULL;
+       } 
+       g_mutex_lock(mutex); 
     if(!mtp_device)
-       {
-            gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))),DEFAULT_LABEL);
-            gtk_widget_set_sensitive(menuitem, TRUE);
-            g_mutex_unlock(mutex);
-            return NULL;
-       }
+    {
+        gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))),DEFAULT_LABEL);
+        gtk_widget_set_sensitive(menuitem, TRUE);
+                g_mutex_unlock(mutex); 
+        return NULL;
+    }
 
     gchar* from_path;
+
     GList *up_list=NULL,*node;
     node=up_list=get_upload_list();
+    gint up_err=0;
     while(node)
     {
         from_path=(gchar*)(node->data);
-        upload_file(from_path);
+        up_err = upload_file(from_path);
+        if(up_err )
+         {
+             show_dialog("An error has occured while uploading...\nUpload failed!");
+             break;
+         }
+         if(exiting)
+         {
+             /*show_dialog("Shutting down MTP while uploading.\nPending uploads were cancelled");*/
+             break;
+         }
+
         node = g_list_next(node);
     }
     g_list_free(up_list);
+#if DEBUG
+    g_print("up_list free ok, seting menuitem ...\n");
+#endif    
 
     gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))),DEFAULT_LABEL);
     gtk_widget_set_sensitive(menuitem, TRUE);
-    g_mutex_unlock(mutex);
+      g_mutex_unlock(mutex); 
+#if DEBUG
+    g_print("upload thread killed exiting upload function\n");
+#endif    
+    g_thread_exit(NULL);
     return NULL;
 }
 
@@ -188,13 +261,17 @@
     {
 #if DEBUG
         g_print("No MTP devices have been found !!!");
-#endif
+#endif  
+        show_dialog("No MTP devices have been found !!!");
+        mtp_initialised = FALSE;
         return;
 
     }
     gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))),DISABLED_LABEL);
     gtk_widget_set_sensitive(menuitem, FALSE);
-    g_thread_create(upload,NULL,FALSE,NULL);    
+    g_thread_create(upload,NULL,FALSE,NULL); 
+    return;
+
 }
 
 void mtp_init(void)
@@ -205,6 +282,7 @@
     g_signal_connect (G_OBJECT (menuitem), "button_press_event",G_CALLBACK (mtp_press), NULL);  
     mutex = g_mutex_new();
     plugin_active = TRUE;
+    exiting=FALSE;
 }
 
 void mtp_cleanup(void)
@@ -214,12 +292,15 @@
 
 #if DEBUG
         if(mtp_initialised)
-            g_print("\n\n                 !!!CAUTION!!! \n\n"
+           {
+               g_print("\n\n                 !!!CAUTION!!! \n\n"
                     "Cleaning up MTP upload plugin, please wait!!!...\n"
                     "This will block until the pending tracks are uploaded,\n"
                     "then it will gracefully close your device\n\n"
                     "!!! FORCING SHUTDOWN NOW MAY CAUSE DAMAGE TO YOUR DEVICE !!!\n\n\n"
                     "Waiting for the MTP mutex to unlock...\n");
+               exiting=TRUE;
+           }
 #endif
         if(mutex)
             g_mutex_lock(mutex);
--- a/src/vorbis/vorbis.c	Fri Aug 17 11:40:30 2007 -0500
+++ b/src/vorbis/vorbis.c	Fri Aug 17 11:58:12 2007 -0500
@@ -608,8 +608,8 @@
     Tuple *tuple = get_song_tuple(filename);
 
     *length = tuple_get_int(tuple, "length");
-    *title = tuple_formatter_process_string(tuple, vorbis_cfg.tag_override ?
-                                  vorbis_cfg.tag_format : cfg.gentitle_format);
+    *title = tuple_formatter_make_title_string(tuple, vorbis_cfg.tag_override ?
+                                            vorbis_cfg.tag_format : get_gentitle_format());
 
     tuple_free(tuple);
 }
@@ -829,8 +829,8 @@
 
     input = get_tuple_for_vorbisfile(vorbisfile, filename, vorbis_is_streaming);
 
-    displaytitle = tuple_formatter_process_string(input, vorbis_cfg.tag_override ?
-                                              vorbis_cfg.tag_format : cfg.gentitle_format);
+    displaytitle = tuple_formatter_make_title_string(input, vorbis_cfg.tag_override ?
+                                                  vorbis_cfg.tag_format : get_gentitle_format());
 
     if ((tmp = vfs_get_metadata(((VFSVorbisFile *) vorbisfile->datasource)->fd, "stream-name")) != NULL)
     {