changeset 346:76047737ea49 trunk

[svn] - rename plugin glue to plugin.c
author nenolod
date Fri, 08 Dec 2006 19:34:32 -0800
parents 213ccf5b5ea5
children f1b620b679b1
files ChangeLog src/scrobbler/Makefile src/scrobbler/plugin.c src/scrobbler/xmms_scrobbler.c
diffstat 4 files changed, 501 insertions(+), 493 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Dec 08 19:33:49 2006 -0800
+++ b/ChangeLog	Fri Dec 08 19:34:32 2006 -0800
@@ -1,3 +1,11 @@
+2006-12-09 03:33:49 +0000  William Pitcock <nenolod@nenolod.net>
+  revision [754]
+  - turn debugging off by default
+  
+  trunk/src/scrobbler/settings.h |    6 +++---
+  1 file changed, 3 insertions(+), 3 deletions(-)
+
+
 2006-12-09 03:31:43 +0000  William Pitcock <nenolod@nenolod.net>
   revision [752]
   - Merge audacious-scrobbler III, new features include:
--- a/src/scrobbler/Makefile	Fri Dec 08 19:33:49 2006 -0800
+++ b/src/scrobbler/Makefile	Fri Dec 08 19:34:32 2006 -0800
@@ -21,7 +21,7 @@
 	md5.c			\
 	scrobbler.c		\
 	gerpok.c		\
-	xmms_scrobbler.c
+	plugin.c
 
 CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) $(BEEP_DEFINES) $(CURL_CFLAGS) -I../../intl -I../..
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/scrobbler/plugin.c	Fri Dec 08 19:34:32 2006 -0800
@@ -0,0 +1,492 @@
+#include "settings.h"
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <audacious/plugin.h>
+#include <audacious/prefswin.h>
+#include <audacious/playlist.h>
+#include <audacious/configdb.h>
+#include <audacious/beepctrl.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <wchar.h>
+#include <sys/time.h>
+
+#include "scrobbler.h"
+#include "gerpok.h"
+#include "gtkstuff.h"
+#include "config.h"
+#include "fmt.h"
+#include "configure.h"
+
+#define XS_CS xmms_scrobbler.xmms_session
+
+typedef struct submit_t
+{
+	int dosubmit, pos_c, len;
+} submit_t;
+
+static void init(void);
+static void cleanup(void);
+static void *xs_thread(void *);
+static void *hs_thread(void *);
+static int sc_going, ge_going;
+static GtkWidget *cfgdlg;
+
+static GThread *pt_scrobbler;
+static GMutex *m_scrobbler;
+static GThread *pt_handshake;
+
+static GeneralPlugin xmms_scrobbler =
+{
+	NULL,
+	NULL,
+	-1,
+	NULL,
+	init,
+	about_show,
+	NULL,
+	cleanup
+};
+
+static void init(void)
+{
+	char *username = NULL, *password = NULL;
+	char *ge_username = NULL, *ge_password = NULL;
+	ConfigDb *cfgfile;
+	sc_going = 1;
+	ge_going = 1;
+	GError **moo = NULL;
+	cfgdlg = create_cfgdlg();
+
+        prefswin_page_new(cfgdlg, "Scrobbler", DATA_DIR "/images/audioscrobbler.png");
+
+	if ((cfgfile = bmp_cfg_db_open()) != NULL) {
+		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "username",
+				&username);
+		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "password",
+				&password);
+		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "ge_username",
+				&ge_username);
+		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "ge_password",
+				&ge_password);
+		bmp_cfg_db_close(cfgfile);
+	}
+
+	if ((!username || !password) || (!*username || !*password))
+	{
+		pdebug("username/password not found - not starting last.fm support",
+			DEBUG);
+		sc_going = 0;
+	}
+	else
+		sc_init(username, password);
+
+	g_free(username);
+	g_free(password);
+	
+	if ((!ge_username || !ge_password) || (!*ge_username || !*ge_password))
+	{
+		pdebug("username/password not found - not starting Gerpok support",
+			DEBUG);
+		ge_going = 0;
+	}
+	else
+		gerpok_sc_init(ge_username, ge_password);
+
+	g_free(ge_username);
+	g_free(ge_password);
+
+	m_scrobbler = g_mutex_new();
+	if ((pt_scrobbler = g_thread_create(xs_thread, m_scrobbler, TRUE, moo)) == NULL)
+	{
+		pdebug(fmt_vastr("Error creating scrobbler thread: %s", moo), DEBUG);
+		sc_going = 0;
+		ge_going = 0;
+		return;
+	}
+
+	if ((pt_handshake = g_thread_create(hs_thread, m_scrobbler, TRUE, NULL)) == NULL)
+	{
+		pdebug(fmt_vastr("Error creating handshake thread: %s", moo), DEBUG);
+		sc_going = 0;
+		ge_going = 0;
+		return;
+	}
+
+	pdebug("plugin started", DEBUG);
+}
+
+static void cleanup(void)
+{
+    g_free (xmms_scrobbler.description);
+    xmms_scrobbler.description = NULL;
+
+        prefswin_page_destroy(cfgdlg);
+
+	if (!sc_going && !ge_going)
+		return;
+	pdebug("about to lock mutex", DEBUG);
+	g_mutex_lock(m_scrobbler);
+	pdebug("locked mutex", DEBUG);
+	sc_going = 0;
+	ge_going = 0;
+	g_mutex_unlock(m_scrobbler);
+	pdebug("joining threads", DEBUG);
+	g_thread_join(pt_scrobbler);
+
+	g_thread_join(pt_handshake);
+
+	sc_cleaner();
+	gerpok_sc_cleaner();
+}
+
+static char ishttp(const char *a)
+{
+	char *tmp, *bp;
+	int status = 0;
+
+	if (!a || !*a)
+		return 0;
+
+	tmp = strdup(a);
+	for (bp = tmp; *bp; bp++)
+		*bp = toupper((int) *bp);
+	if (strstr(tmp, "HTTP://"))
+		status = -1;
+	free(tmp);
+	return status;
+}
+
+/* Following code thanks to nosuke 
+ *
+ * It should probably be cleaned up
+ */
+static submit_t get_song_status(void)
+{
+	static int pos_c, playlistlen_c, playtime_c, time_c,
+		pos_p = 0, playlistlen_p = 0, playtime_p = 0,
+		playtime_i = 0, time_i = 0,
+		playtime_ofs = 0;
+	static char *file_c = NULL, *file_p = NULL; 
+
+	static enum playstatus {
+		ps_stop, ps_play, ps_pause
+	} ps_c, ps_p = ps_stop;
+
+	static int submitted = 0, changed, seeked, repeat,
+		filechanged, rewind, len = 0;
+
+	static enum state {
+		start, stop, pause, restart, playing, pausing, stopping
+	} playstate;
+
+	submit_t dosubmit;
+
+	struct timeval timetmp;
+
+	/* clear dosubmit */
+	dosubmit.dosubmit = dosubmit.pos_c = dosubmit.len = 0;
+
+	/* current music number */
+	pos_c = xmms_remote_get_playlist_pos(XS_CS);
+	/* current file name */
+	file_c = xmms_remote_get_playlist_file(XS_CS, pos_c); 
+	/* total number */
+	playlistlen_c = xmms_remote_get_playlist_length(XS_CS);
+	/* current playtime */
+	playtime_c = xmms_remote_get_output_time(XS_CS); 
+	/* total length */
+	len = xmms_remote_get_playlist_time(XS_CS, pos_c); 
+
+	/* current time (ms) */
+	gettimeofday(&timetmp, NULL);
+	time_c = timetmp.tv_sec * 1000 + timetmp.tv_usec / 1000; 
+
+	/* current status */
+	if( xmms_remote_is_paused(XS_CS) ) {
+		ps_c = ps_pause;
+	}else if( xmms_remote_is_playing(XS_CS) ) {
+		ps_c = ps_play;
+	}else{
+		ps_c = ps_stop;
+	}
+
+	/* repeat setting */
+	repeat = xmms_remote_is_repeat(XS_CS);
+
+	/*
+#ifdef MAKE_XMMS
+	// advance setting (required xmms-1.2.11 or over)
+	advance = xmms_remote_is_advance(XS_CS);
+#else
+	advance = 1;
+#endif
+	*/
+
+	if( ps_p == ps_stop && ps_c == ps_stop )        playstate = stopping;
+	else if( ps_p == ps_stop && ps_c == ps_play )   playstate = start;
+	/* else if( ps_p == ps_stop && ps_c == ps_pause ) ; */
+	else if( ps_p == ps_play && ps_c == ps_play )   playstate = playing;
+	else if( ps_p == ps_play && ps_c == ps_stop )   playstate = stop;
+	else if( ps_p == ps_play && ps_c == ps_pause )  playstate = pause;
+	else if( ps_p == ps_pause && ps_c == ps_pause ) playstate = pausing;
+	else if( ps_p == ps_pause && ps_c == ps_play )  playstate = restart;
+	else if( ps_p == ps_pause && ps_c == ps_stop )  playstate = stop;
+	else playstate = stopping;
+
+	/* filename has changed */
+	if( !(file_p == NULL && file_c == NULL) &&
+	    ((file_p == NULL && file_c != NULL) ||
+		 (file_p != NULL && file_c == NULL) ||
+		 (file_p != NULL && file_c != NULL && strcmp(file_c, file_p))) ){
+		filechanged = 1;
+		pdebug("*** filechange ***", SUB_DEBUG);
+	}else{
+		filechanged = 0;
+	}
+	if( file_c == NULL ){ len = 0; }
+
+	/* whole rewind has occurred (maybe) */
+	if( len != 0 && len - (playtime_p - playtime_c) < 3000 ){
+		rewind = 1;
+		pdebug("*** rewind ***", SUB_DEBUG);
+	}else{
+		rewind = 0;
+	}
+
+
+	changed = 0;
+	seeked = 0;
+
+	switch( playstate ){
+	case start:
+	  pdebug("*** START ***", SUB_DEBUG);
+	  break;
+	case stop:
+	  pdebug("*** STOP ***", SUB_DEBUG);
+	  len = 0;
+	  break;
+	case pause: 
+	  pdebug("*** PAUSE ***", SUB_DEBUG);
+	  playtime_ofs += playtime_c - playtime_i; /* save playtime */
+	  break;
+	case restart: 
+	  pdebug("*** RESTART ***", SUB_DEBUG);
+	  playtime_i  = playtime_c; /* restore playtime */
+	  break;
+	case playing:
+	  if( (playtime_c < playtime_p) || /* back */
+		  ( (playtime_c - playtime_i) - (time_c - time_i) > 3000 )
+	          /* forward */
+		  ) { 
+		seeked = 1;
+	  }
+
+	  if( filechanged || /* filename has changed */
+		  ( !filechanged && /* filename has not changed... */
+			/* (( rewind && (repeat && (!advance ||
+	                   (pos_c == 0 && playlistlen_c == 1 )))) || */
+			/* looping with only one file */
+			(( pos_c == 0 && playlistlen_c == 1 && repeat
+				&& rewind ) || 
+			 /* looping? */
+			 ( pos_p == pos_c && rewind ) ||
+			 
+			 ( pos_p != pos_c && seeked ) ||
+			 /* skip from current music to next music, 
+			    which has the same filename as previous one */
+			 ( pos_p < pos_c && playtime_c < playtime_p ) || 
+			 /* current song has removed from playlist 
+			    but the next (following) song has the same
+	                    filename */
+			 ( playlistlen_p > playlistlen_c
+				&& playtime_c < playtime_p )))){
+		pdebug("*** CHANGE ***",SUB_DEBUG);
+		pdebug(fmt_vastr(" filechanged = %d",filechanged),SUB_DEBUG);
+		pdebug(fmt_vastr(" pos_c = %d",pos_c),SUB_DEBUG);
+		pdebug(fmt_vastr(" pos_p = %d",pos_p),SUB_DEBUG);
+		pdebug(fmt_vastr(" rewind = %d", rewind),SUB_DEBUG);
+		pdebug(fmt_vastr(" seeked = %d", seeked),SUB_DEBUG);
+		pdebug(fmt_vastr(" playtime_c = %d", playtime_c),SUB_DEBUG);
+		pdebug(fmt_vastr(" playtime_p = %d", playtime_p),SUB_DEBUG);
+		pdebug(fmt_vastr(" playlistlen_c = %d", playlistlen_p),
+			SUB_DEBUG);
+		pdebug(fmt_vastr(" playlistlen_p = %d", playlistlen_p),
+			SUB_DEBUG);
+		changed = 1;
+		seeked = 0;
+
+		if (file_p != NULL)
+		{
+			g_free(file_p);
+			file_p = NULL;
+		}
+	  }else if( seeked ) { 
+		seeked = 1;
+		pdebug("*** SEEK ***", SUB_DEBUG);
+	  }
+
+	  break;
+	case pausing: 
+	  if(playtime_c != playtime_p){
+		pdebug("*** SEEK ***", SUB_DEBUG);
+		seeked = 1;
+	  }
+	  break;
+	case stopping:
+	  len = 0;
+	  break;
+	default:
+	  pdebug("*** unknown state tranfer!!! ***", SUB_DEBUG);
+	  break;
+	}
+
+	
+	if( playstate == start || changed || (seeked && !submitted) ){
+	  /* reset counter */
+	  pdebug(" <<< reset counter >>>", SUB_DEBUG);
+
+	  submitted = 0;
+	  playtime_ofs = 0;
+	  playtime_i = playtime_c;
+	  time_i = time_c;
+
+	}else{
+	  /* check playtime for submitting */
+	  if( !submitted ){
+		if( len > 30 * 1000 &&
+			/* len < 30 *60 * 1000 &&  // crazy rule!!! */
+			( 
+			 (playtime_ofs + playtime_c - playtime_i > len / 2) ||
+			 (playtime_ofs + playtime_c - playtime_i > 240 * 1000) 
+			 /* (playtime_c - playtime_i > 10 * 1000)// for debug */
+			 )){
+		  pdebug("*** submitting requirements are satisfied.",
+			SUB_DEBUG);
+		  pdebug(fmt_vastr("    len = %d, playtime = %d",
+			len / 1000, (playtime_c - playtime_i)/1000 ),
+			SUB_DEBUG);
+		  submitted = 1;
+		  dosubmit.dosubmit = 1;
+	          dosubmit.pos_c = pos_c;
+	          dosubmit.len = len;
+		}
+	  }
+	}
+
+	g_free(file_p);
+
+	/* keep current value for next iteration */
+	ps_p = ps_c;
+	file_p = file_c;
+	playtime_p = playtime_c;
+	pos_p = pos_c;
+	playlistlen_p = playlistlen_c;
+
+	return dosubmit;
+}
+
+static void *xs_thread(void *data __attribute__((unused)))
+{
+	int run = 1;
+	submit_t dosubmit;
+	
+	while (run) {
+		/* Error catching */
+		if(sc_catch_error())
+		{
+			errorbox_show(sc_fetch_error());
+			sc_clear_error();
+		}
+
+		if(gerpok_sc_catch_error())
+		{
+			errorbox_show(gerpok_sc_fetch_error());
+			gerpok_sc_clear_error();
+		}
+
+		/* Check for ability to submit */
+		dosubmit = get_song_status();
+
+		if(dosubmit.dosubmit) {
+			TitleInput *tuple;
+
+			pdebug("Submitting song.", DEBUG);
+
+			tuple = playlist_get_tuple(dosubmit.pos_c);
+
+			if (ishttp(tuple->file_name))
+				continue;
+
+			if(tuple->performer != NULL && tuple->track_name != NULL)
+			{
+				pdebug(fmt_vastr(
+					"submitting artist: %s, title: %s",
+					tuple->performer, tuple->track_name), DEBUG);
+				sc_addentry(m_scrobbler, tuple,
+					dosubmit.len/1000);
+				gerpok_sc_addentry(m_scrobbler, tuple,
+					dosubmit.len/1000);
+			}
+			else
+				pdebug("tuple does not contain an artist or a title, not submitting.", DEBUG);
+		}
+		g_mutex_lock(m_scrobbler);
+		run = (sc_going != 0 || ge_going != 0);
+		g_mutex_unlock(m_scrobbler);
+		g_usleep(100000);
+	}
+	pdebug("scrobbler thread: exiting", DEBUG);
+	g_thread_exit(NULL);
+
+	return NULL;
+}
+
+static void *hs_thread(void *data __attribute__((unused)))
+{
+	int run = 1;
+	
+	while(run)
+	{
+		if(sc_idle(m_scrobbler))
+		{
+			pdebug("Giving up due to fatal error", DEBUG);
+			g_mutex_lock(m_scrobbler);
+			sc_going = 0;
+			g_mutex_lock(m_scrobbler);
+		}
+
+		if(gerpok_sc_idle(m_scrobbler))
+		{
+			pdebug("Giving up due to fatal error", DEBUG);
+			g_mutex_lock(m_scrobbler);
+			ge_going = 0;
+			g_mutex_lock(m_scrobbler);
+		}
+
+		g_mutex_lock(m_scrobbler);
+		run = (sc_going != 0 || ge_going != 0);
+		g_mutex_unlock(m_scrobbler);
+		g_usleep(1000000);
+	}
+	pdebug("handshake thread: exiting", DEBUG);
+	g_thread_exit(NULL);
+
+	return NULL;
+}
+
+GeneralPlugin *get_gplugin_info(void)
+{
+	xmms_scrobbler.description = g_strdup_printf(_("Scrobbler Plugin"));
+	return &xmms_scrobbler;
+}
--- a/src/scrobbler/xmms_scrobbler.c	Fri Dec 08 19:33:49 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,492 +0,0 @@
-#include "settings.h"
-#include "config.h"
-
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <audacious/plugin.h>
-#include <audacious/prefswin.h>
-#include <audacious/playlist.h>
-#include <audacious/configdb.h>
-#include <audacious/beepctrl.h>
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <wchar.h>
-#include <sys/time.h>
-
-#include "scrobbler.h"
-#include "gerpok.h"
-#include "gtkstuff.h"
-#include "config.h"
-#include "fmt.h"
-#include "configure.h"
-
-#define XS_CS xmms_scrobbler.xmms_session
-
-typedef struct submit_t
-{
-	int dosubmit, pos_c, len;
-} submit_t;
-
-static void init(void);
-static void cleanup(void);
-static void *xs_thread(void *);
-static void *hs_thread(void *);
-static int sc_going, ge_going;
-static GtkWidget *cfgdlg;
-
-static GThread *pt_scrobbler;
-static GMutex *m_scrobbler;
-static GThread *pt_handshake;
-
-static GeneralPlugin xmms_scrobbler =
-{
-	NULL,
-	NULL,
-	-1,
-	NULL,
-	init,
-	about_show,
-	NULL,
-	cleanup
-};
-
-static void init(void)
-{
-	char *username = NULL, *password = NULL;
-	char *ge_username = NULL, *ge_password = NULL;
-	ConfigDb *cfgfile;
-	sc_going = 1;
-	ge_going = 1;
-	GError **moo = NULL;
-	cfgdlg = create_cfgdlg();
-
-        prefswin_page_new(cfgdlg, "Scrobbler", DATA_DIR "/images/audioscrobbler.png");
-
-	if ((cfgfile = bmp_cfg_db_open()) != NULL) {
-		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "username",
-				&username);
-		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "password",
-				&password);
-		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "ge_username",
-				&ge_username);
-		bmp_cfg_db_get_string(cfgfile, "audioscrobbler", "ge_password",
-				&ge_password);
-		bmp_cfg_db_close(cfgfile);
-	}
-
-	if ((!username || !password) || (!*username || !*password))
-	{
-		pdebug("username/password not found - not starting last.fm support",
-			DEBUG);
-		sc_going = 0;
-	}
-	else
-		sc_init(username, password);
-
-	g_free(username);
-	g_free(password);
-	
-	if ((!ge_username || !ge_password) || (!*ge_username || !*ge_password))
-	{
-		pdebug("username/password not found - not starting Gerpok support",
-			DEBUG);
-		ge_going = 0;
-	}
-	else
-		gerpok_sc_init(ge_username, ge_password);
-
-	g_free(ge_username);
-	g_free(ge_password);
-
-	m_scrobbler = g_mutex_new();
-	if ((pt_scrobbler = g_thread_create(xs_thread, m_scrobbler, TRUE, moo)) == NULL)
-	{
-		pdebug(fmt_vastr("Error creating scrobbler thread: %s", moo), DEBUG);
-		sc_going = 0;
-		ge_going = 0;
-		return;
-	}
-
-	if ((pt_handshake = g_thread_create(hs_thread, m_scrobbler, TRUE, NULL)) == NULL)
-	{
-		pdebug(fmt_vastr("Error creating handshake thread: %s", moo), DEBUG);
-		sc_going = 0;
-		ge_going = 0;
-		return;
-	}
-
-	pdebug("plugin started", DEBUG);
-}
-
-static void cleanup(void)
-{
-    g_free (xmms_scrobbler.description);
-    xmms_scrobbler.description = NULL;
-
-        prefswin_page_destroy(cfgdlg);
-
-	if (!sc_going && !ge_going)
-		return;
-	pdebug("about to lock mutex", DEBUG);
-	g_mutex_lock(m_scrobbler);
-	pdebug("locked mutex", DEBUG);
-	sc_going = 0;
-	ge_going = 0;
-	g_mutex_unlock(m_scrobbler);
-	pdebug("joining threads", DEBUG);
-	g_thread_join(pt_scrobbler);
-
-	g_thread_join(pt_handshake);
-
-	sc_cleaner();
-	gerpok_sc_cleaner();
-}
-
-static char ishttp(const char *a)
-{
-	char *tmp, *bp;
-	int status = 0;
-
-	if (!a || !*a)
-		return 0;
-
-	tmp = strdup(a);
-	for (bp = tmp; *bp; bp++)
-		*bp = toupper((int) *bp);
-	if (strstr(tmp, "HTTP://"))
-		status = -1;
-	free(tmp);
-	return status;
-}
-
-/* Following code thanks to nosuke 
- *
- * It should probably be cleaned up
- */
-static submit_t get_song_status(void)
-{
-	static int pos_c, playlistlen_c, playtime_c, time_c,
-		pos_p = 0, playlistlen_p = 0, playtime_p = 0,
-		playtime_i = 0, time_i = 0,
-		playtime_ofs = 0;
-	static char *file_c = NULL, *file_p = NULL; 
-
-	static enum playstatus {
-		ps_stop, ps_play, ps_pause
-	} ps_c, ps_p = ps_stop;
-
-	static int submitted = 0, changed, seeked, repeat,
-		filechanged, rewind, len = 0;
-
-	static enum state {
-		start, stop, pause, restart, playing, pausing, stopping
-	} playstate;
-
-	submit_t dosubmit;
-
-	struct timeval timetmp;
-
-	/* clear dosubmit */
-	dosubmit.dosubmit = dosubmit.pos_c = dosubmit.len = 0;
-
-	/* current music number */
-	pos_c = xmms_remote_get_playlist_pos(XS_CS);
-	/* current file name */
-	file_c = xmms_remote_get_playlist_file(XS_CS, pos_c); 
-	/* total number */
-	playlistlen_c = xmms_remote_get_playlist_length(XS_CS);
-	/* current playtime */
-	playtime_c = xmms_remote_get_output_time(XS_CS); 
-	/* total length */
-	len = xmms_remote_get_playlist_time(XS_CS, pos_c); 
-
-	/* current time (ms) */
-	gettimeofday(&timetmp, NULL);
-	time_c = timetmp.tv_sec * 1000 + timetmp.tv_usec / 1000; 
-
-	/* current status */
-	if( xmms_remote_is_paused(XS_CS) ) {
-		ps_c = ps_pause;
-	}else if( xmms_remote_is_playing(XS_CS) ) {
-		ps_c = ps_play;
-	}else{
-		ps_c = ps_stop;
-	}
-
-	/* repeat setting */
-	repeat = xmms_remote_is_repeat(XS_CS);
-
-	/*
-#ifdef MAKE_XMMS
-	// advance setting (required xmms-1.2.11 or over)
-	advance = xmms_remote_is_advance(XS_CS);
-#else
-	advance = 1;
-#endif
-	*/
-
-	if( ps_p == ps_stop && ps_c == ps_stop )        playstate = stopping;
-	else if( ps_p == ps_stop && ps_c == ps_play )   playstate = start;
-	/* else if( ps_p == ps_stop && ps_c == ps_pause ) ; */
-	else if( ps_p == ps_play && ps_c == ps_play )   playstate = playing;
-	else if( ps_p == ps_play && ps_c == ps_stop )   playstate = stop;
-	else if( ps_p == ps_play && ps_c == ps_pause )  playstate = pause;
-	else if( ps_p == ps_pause && ps_c == ps_pause ) playstate = pausing;
-	else if( ps_p == ps_pause && ps_c == ps_play )  playstate = restart;
-	else if( ps_p == ps_pause && ps_c == ps_stop )  playstate = stop;
-	else playstate = stopping;
-
-	/* filename has changed */
-	if( !(file_p == NULL && file_c == NULL) &&
-	    ((file_p == NULL && file_c != NULL) ||
-		 (file_p != NULL && file_c == NULL) ||
-		 (file_p != NULL && file_c != NULL && strcmp(file_c, file_p))) ){
-		filechanged = 1;
-		pdebug("*** filechange ***", SUB_DEBUG);
-	}else{
-		filechanged = 0;
-	}
-	if( file_c == NULL ){ len = 0; }
-
-	/* whole rewind has occurred (maybe) */
-	if( len != 0 && len - (playtime_p - playtime_c) < 3000 ){
-		rewind = 1;
-		pdebug("*** rewind ***", SUB_DEBUG);
-	}else{
-		rewind = 0;
-	}
-
-
-	changed = 0;
-	seeked = 0;
-
-	switch( playstate ){
-	case start:
-	  pdebug("*** START ***", SUB_DEBUG);
-	  break;
-	case stop:
-	  pdebug("*** STOP ***", SUB_DEBUG);
-	  len = 0;
-	  break;
-	case pause: 
-	  pdebug("*** PAUSE ***", SUB_DEBUG);
-	  playtime_ofs += playtime_c - playtime_i; /* save playtime */
-	  break;
-	case restart: 
-	  pdebug("*** RESTART ***", SUB_DEBUG);
-	  playtime_i  = playtime_c; /* restore playtime */
-	  break;
-	case playing:
-	  if( (playtime_c < playtime_p) || /* back */
-		  ( (playtime_c - playtime_i) - (time_c - time_i) > 3000 )
-	          /* forward */
-		  ) { 
-		seeked = 1;
-	  }
-
-	  if( filechanged || /* filename has changed */
-		  ( !filechanged && /* filename has not changed... */
-			/* (( rewind && (repeat && (!advance ||
-	                   (pos_c == 0 && playlistlen_c == 1 )))) || */
-			/* looping with only one file */
-			(( pos_c == 0 && playlistlen_c == 1 && repeat
-				&& rewind ) || 
-			 /* looping? */
-			 ( pos_p == pos_c && rewind ) ||
-			 
-			 ( pos_p != pos_c && seeked ) ||
-			 /* skip from current music to next music, 
-			    which has the same filename as previous one */
-			 ( pos_p < pos_c && playtime_c < playtime_p ) || 
-			 /* current song has removed from playlist 
-			    but the next (following) song has the same
-	                    filename */
-			 ( playlistlen_p > playlistlen_c
-				&& playtime_c < playtime_p )))){
-		pdebug("*** CHANGE ***",SUB_DEBUG);
-		pdebug(fmt_vastr(" filechanged = %d",filechanged),SUB_DEBUG);
-		pdebug(fmt_vastr(" pos_c = %d",pos_c),SUB_DEBUG);
-		pdebug(fmt_vastr(" pos_p = %d",pos_p),SUB_DEBUG);
-		pdebug(fmt_vastr(" rewind = %d", rewind),SUB_DEBUG);
-		pdebug(fmt_vastr(" seeked = %d", seeked),SUB_DEBUG);
-		pdebug(fmt_vastr(" playtime_c = %d", playtime_c),SUB_DEBUG);
-		pdebug(fmt_vastr(" playtime_p = %d", playtime_p),SUB_DEBUG);
-		pdebug(fmt_vastr(" playlistlen_c = %d", playlistlen_p),
-			SUB_DEBUG);
-		pdebug(fmt_vastr(" playlistlen_p = %d", playlistlen_p),
-			SUB_DEBUG);
-		changed = 1;
-		seeked = 0;
-
-		if (file_p != NULL)
-		{
-			g_free(file_p);
-			file_p = NULL;
-		}
-	  }else if( seeked ) { 
-		seeked = 1;
-		pdebug("*** SEEK ***", SUB_DEBUG);
-	  }
-
-	  break;
-	case pausing: 
-	  if(playtime_c != playtime_p){
-		pdebug("*** SEEK ***", SUB_DEBUG);
-		seeked = 1;
-	  }
-	  break;
-	case stopping:
-	  len = 0;
-	  break;
-	default:
-	  pdebug("*** unknown state tranfer!!! ***", SUB_DEBUG);
-	  break;
-	}
-
-	
-	if( playstate == start || changed || (seeked && !submitted) ){
-	  /* reset counter */
-	  pdebug(" <<< reset counter >>>", SUB_DEBUG);
-
-	  submitted = 0;
-	  playtime_ofs = 0;
-	  playtime_i = playtime_c;
-	  time_i = time_c;
-
-	}else{
-	  /* check playtime for submitting */
-	  if( !submitted ){
-		if( len > 30 * 1000 &&
-			/* len < 30 *60 * 1000 &&  // crazy rule!!! */
-			( 
-			 (playtime_ofs + playtime_c - playtime_i > len / 2) ||
-			 (playtime_ofs + playtime_c - playtime_i > 240 * 1000) 
-			 /* (playtime_c - playtime_i > 10 * 1000)// for debug */
-			 )){
-		  pdebug("*** submitting requirements are satisfied.",
-			SUB_DEBUG);
-		  pdebug(fmt_vastr("    len = %d, playtime = %d",
-			len / 1000, (playtime_c - playtime_i)/1000 ),
-			SUB_DEBUG);
-		  submitted = 1;
-		  dosubmit.dosubmit = 1;
-	          dosubmit.pos_c = pos_c;
-	          dosubmit.len = len;
-		}
-	  }
-	}
-
-	g_free(file_p);
-
-	/* keep current value for next iteration */
-	ps_p = ps_c;
-	file_p = file_c;
-	playtime_p = playtime_c;
-	pos_p = pos_c;
-	playlistlen_p = playlistlen_c;
-
-	return dosubmit;
-}
-
-static void *xs_thread(void *data __attribute__((unused)))
-{
-	int run = 1;
-	submit_t dosubmit;
-	
-	while (run) {
-		/* Error catching */
-		if(sc_catch_error())
-		{
-			errorbox_show(sc_fetch_error());
-			sc_clear_error();
-		}
-
-		if(gerpok_sc_catch_error())
-		{
-			errorbox_show(gerpok_sc_fetch_error());
-			gerpok_sc_clear_error();
-		}
-
-		/* Check for ability to submit */
-		dosubmit = get_song_status();
-
-		if(dosubmit.dosubmit) {
-			TitleInput *tuple;
-
-			pdebug("Submitting song.", DEBUG);
-
-			tuple = playlist_get_tuple(dosubmit.pos_c);
-
-			if (ishttp(tuple->file_name))
-				continue;
-
-			if(tuple->performer != NULL && tuple->track_name != NULL)
-			{
-				pdebug(fmt_vastr(
-					"submitting artist: %s, title: %s",
-					tuple->performer, tuple->track_name), DEBUG);
-				sc_addentry(m_scrobbler, tuple,
-					dosubmit.len/1000);
-				gerpok_sc_addentry(m_scrobbler, tuple,
-					dosubmit.len/1000);
-			}
-			else
-				pdebug("tuple does not contain an artist or a title, not submitting.", DEBUG);
-		}
-		g_mutex_lock(m_scrobbler);
-		run = (sc_going != 0 || ge_going != 0);
-		g_mutex_unlock(m_scrobbler);
-		g_usleep(100000);
-	}
-	pdebug("scrobbler thread: exiting", DEBUG);
-	g_thread_exit(NULL);
-
-	return NULL;
-}
-
-static void *hs_thread(void *data __attribute__((unused)))
-{
-	int run = 1;
-	
-	while(run)
-	{
-		if(sc_idle(m_scrobbler))
-		{
-			pdebug("Giving up due to fatal error", DEBUG);
-			g_mutex_lock(m_scrobbler);
-			sc_going = 0;
-			g_mutex_lock(m_scrobbler);
-		}
-
-		if(gerpok_sc_idle(m_scrobbler))
-		{
-			pdebug("Giving up due to fatal error", DEBUG);
-			g_mutex_lock(m_scrobbler);
-			ge_going = 0;
-			g_mutex_lock(m_scrobbler);
-		}
-
-		g_mutex_lock(m_scrobbler);
-		run = (sc_going != 0 || ge_going != 0);
-		g_mutex_unlock(m_scrobbler);
-		g_usleep(1000000);
-	}
-	pdebug("handshake thread: exiting", DEBUG);
-	g_thread_exit(NULL);
-
-	return NULL;
-}
-
-GeneralPlugin *get_gplugin_info(void)
-{
-	xmms_scrobbler.description = g_strdup_printf(_("Scrobbler Plugin"));
-	return &xmms_scrobbler;
-}