Index: apps/SOURCES
===================================================================
RCS file: /cvsroot/rockbox/apps/SOURCES,v
retrieving revision 1.44
diff -u -r1.44 SOURCES
--- apps/SOURCES	26 Mar 2006 11:33:41 -0000	1.44
+++ apps/SOURCES	17 Apr 2006 23:56:16 -0000
@@ -27,6 +27,7 @@
 tree.c
 tagtree.c
 filetree.c
+scrobbler.c
 
 screen_access.c
 gui/buttonbar.c
Index: apps/main.c
===================================================================
RCS file: /cvsroot/rockbox/apps/main.c,v
retrieving revision 1.169
diff -u -r1.169 main.c
--- apps/main.c	13 Apr 2006 21:20:13 -0000	1.169
+++ apps/main.c	17 Apr 2006 23:56:17 -0000
@@ -65,6 +65,7 @@
 #include "lang.h"
 #include "string.h"
 #include "splash.h"
+#include "scrobbler.h"
 
 #if (CONFIG_CODEC == SWCODEC)
 #include "playback.h"
@@ -424,6 +425,7 @@
     pcm_rec_init();
 #endif
     talk_init();
+    scrobbler_init();
     /* runtime database has to be initialized after audio_init() */
     cpu_boost(false);
 
Index: apps/scrobbler.c
===================================================================
RCS file: apps/scrobbler.c
diff -N apps/scrobbler.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ apps/scrobbler.c	17 Apr 2006 23:56:17 -0000
@@ -0,0 +1,166 @@
+
+/* mktime() code taken from lynx-2.8.5 source, written
+ by Philippe De Muyter <phdm@macqel.be>
+
+Audioscrobbler spec at:
+http://www.audioscrobbler.net/wiki/Portable_Player_Logging
+*/
+
+#include "file.h"
+#include "sprintf.h"
+#include "playback.h"
+#include "logf.h"
+#include "id3.h"
+#ifdef CONFIG_RTC
+#include "time.h"
+#include "timefuncs.h"
+#endif
+
+#include "scrobbler.h"
+
+int scrobbler_fd = -1;
+
+struct mp3entry scrobbler_entry;
+bool pending = false;
+char rating;
+#ifdef CONFIG_RTC
+time_t timestamp;
+#else
+long timestamp;
+#endif
+
+#ifdef CONFIG_RTC
+static time_t mktime(struct tm *t)
+{
+	short month, year;
+	time_t	result;
+	static int	m_to_d[12] =
+		{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+	month = t->tm_mon;
+	year = t->tm_year + month / 12 + 1900;
+	month %= 12;
+	if (month < 0)
+	{
+		year -= 1;
+		month += 12;
+	}
+	result = (year - 1970) * 365 + (year - 1969) / 4 + m_to_d[month];
+	result = (year - 1970) * 365 + m_to_d[month];
+	if (month <= 1)
+		year -= 1;
+	result += (year - 1968) / 4;
+	result -= (year - 1900) / 100;
+	result += (year - 1600) / 400;
+	result += t->tm_mday;
+	result -= 1;
+	result *= 24;
+	result += t->tm_hour;
+	result *= 60;
+	result += t->tm_min;
+	result *= 60;
+	result += t->tm_sec;
+	return(result);
+}
+#endif
+
+void writescrobblerentry(void)
+{
+    scrobbler_fd = open(SCROBBLER_FILE, O_RDWR | O_APPEND);
+    if(scrobbler_fd >= 0)
+    {
+#ifdef CONFIG_RTC
+        if ((mktime(get_time()) - timestamp) >
+            (long)(scrobbler_entry.length/2000))
+#else
+    // TODO: handle current_time wrapping 
+        if ((current_time - timestamp)/HZ >
+            (scrobbler_entry.length/2000))
+#endif
+            rating = 0x4C; /* "L" */
+    
+        fdprintf(scrobbler_fd, "%s\t", scrobbler_entry.artist);
+        fdprintf(scrobbler_fd, "%s\t", scrobbler_entry.album);
+        fdprintf(scrobbler_fd, "%s\t", scrobbler_entry.title);
+        fdprintf(scrobbler_fd, "%d\t", scrobbler_entry.tracknum);
+        fdprintf(scrobbler_fd, "%d\t", (int)scrobbler_entry.length/1000);
+        fdprintf(scrobbler_fd, "%c\t", rating);
+#ifdef CONFIG_RTC
+        fdprintf(scrobbler_fd, "%ld\t", (long)timestamp);
+#else
+        fdprintf(scrobbler_fd, "\t\t");
+#endif
+        fdprintf(scrobbler_fd, "\n");
+
+        close(scrobbler_fd);
+    }
+    else
+    {
+        logf("SCROBBLER: error writing file");
+    }
+}
+
+void addscrobblerentry(struct mp3entry *id)
+{
+    if (pending)
+        writescrobblerentry();
+
+    if (id->elapsed > (id->length/2))
+    {
+        /* ignore entry if it's resumed with > 50% played */
+        pending = false;
+    }
+    else
+    {
+        copy_mp3entry(&scrobbler_entry, id);
+
+        rating = 0x53; /* "S" */
+#ifdef CONFIG_RTC
+        timestamp = mktime(get_time());
+#else
+        timestamp = current_tick;
+#endif
+
+        pending = true;
+    }
+}
+
+int scrobbler_init(void)
+{
+#if 0
+    if(!global_settings.scrobber)
+        return -1;
+#endif
+
+    scrobbler_fd = open(SCROBBLER_FILE, O_RDONLY);
+    if(scrobbler_fd < 0)
+    {
+        scrobbler_fd = open(SCROBBLER_FILE, O_RDWR | O_CREAT);
+        if(scrobbler_fd >= 0)
+        {
+            fdprintf(scrobbler_fd, "AUDIOSCROBBLER/%s\n", SCROBBLER_VERSION);
+            close(scrobbler_fd);
+        }
+        else
+        {
+            logf("SCROBBLER: cannnot create log file");
+            return -1;
+        }
+    }
+    close(scrobbler_fd);
+
+    audio_set_track_changed_event(&addscrobblerentry);
+
+    return 1;
+}
+
+void scrobbler_shutdown(void)
+{
+    if (pending)
+    {
+        writescrobblerentry();
+        pending = false;
+    }
+
+    audio_set_track_changed_event(NULL);
+}
Index: apps/scrobbler.h
===================================================================
RCS file: apps/scrobbler.h
diff -N apps/scrobbler.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ apps/scrobbler.h	17 Apr 2006 23:56:17 -0000
@@ -0,0 +1,10 @@
+#define SCROBBLER_VERSION "1.0"
+#define SCROBBLER_FILE "/.scrobbler.log"
+
+#if defined(CONFIG_RTC) && !defined(SIMULATOR)
+typedef long time_t;
+#endif
+
+void addscrobblerentry(struct mp3entry *id);
+int scrobbler_init(void);
+void scrobbler_shutdown(void);
Index: apps/tree.c
===================================================================
RCS file: /cvsroot/rockbox/apps/tree.c,v
retrieving revision 1.399
diff -u -r1.399 tree.c
--- apps/tree.c	15 Apr 2006 13:57:15 -0000	1.399
+++ apps/tree.c	17 Apr 2006 23:56:18 -0000
@@ -63,6 +63,7 @@
 #include "dircache.h"
 #include "tagcache.h"
 #include "yesno.h"
+#include "scrobbler.h"
 
 /* gui api */
 #include "list.h"
@@ -1331,6 +1332,7 @@
 /* These two functions are called by the USB and shutdown handlers */
 void tree_flush(void)
 {
+    scrobbler_shutdown();
     tagcache_stop_scan();
     playlist_shutdown();
 
@@ -1374,6 +1376,7 @@
             gui_textarea_clear(&screens[i]);
         }
     }
+    scrobbler_init();
     tagcache_start_scan();
 #endif
 }
