diff options
| author | Linus Nielsen Feltzing <linus@haxx.se> | 2006-10-19 09:42:58 +0000 |
|---|---|---|
| committer | Linus Nielsen Feltzing <linus@haxx.se> | 2006-10-19 09:42:58 +0000 |
| commit | da153da0be485aa4b937d58ee209eda7fb342053 (patch) | |
| tree | 3506b6bba4935fa252250b892d023203e54f3513 /apps/scrobbler.c | |
| parent | 1645d32aa38bd61806125c8d6b1c44fa3ac0f3ca (diff) | |
| download | rockbox-da153da0be485aa4b937d58ee209eda7fb342053.zip rockbox-da153da0be485aa4b937d58ee209eda7fb342053.tar.gz rockbox-da153da0be485aa4b937d58ee209eda7fb342053.tar.bz2 rockbox-da153da0be485aa4b937d58ee209eda7fb342053.tar.xz | |
Patch #5166 by Robert Keevil - Last.fm logging
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11269 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/scrobbler.c')
| -rwxr-xr-x | apps/scrobbler.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/apps/scrobbler.c b/apps/scrobbler.c new file mode 100755 index 0000000..68c5e9a --- /dev/null +++ b/apps/scrobbler.c @@ -0,0 +1,263 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Robert Keevil + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +/* +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" +#include "kernel.h" +#include "audio.h" +#include "buffer.h" +#include "settings.h" + +#ifndef SIMULATOR +#include "ata.h" +#endif + +#ifdef CONFIG_RTC +#include "time.h" +#include "timefuncs.h" +#endif + +#include "scrobbler.h" + +#define SCROBBLER_VERSION "1.0" + +#ifdef CONFIG_RTC +#define SCROBBLER_FILE "/.scrobbler.log" +#else +#define SCROBBLER_FILE "/.scrobbler-timeless.log" +#endif + +/* increment this on any code change that effects output */ +/* replace with CVS Revision keyword? */ +#define SCROBBLER_REVISION "1.0" + +#define SCROBBLER_MAX_CACHE 32 +/* longest entry I've had is 323, add a safety margin */ +#define SCROBBLER_CACHE_LEN 512 + +static char* scrobbler_cache; + +static int scrobbler_fd = -1; +static int cache_pos; +static struct mp3entry scrobbler_entry; +static bool pending = false; +static bool scrobbler_initialised = false; +#ifdef CONFIG_RTC +static time_t timestamp; +#else +static unsigned long timestamp; +#endif + +/* Crude work-around for Archos Sims - return a set amount */ +#if (CONFIG_CODEC != SWCODEC) && defined(SIMULATOR) +unsigned long audio_prev_elapsed(void) +{ + return 120000; +} +#endif + +static void write_cache(void) +{ + int i; + + /* If the file doesn't exist, create it. + Check at each write since file may be deleted at any time */ + 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); + fdprintf(scrobbler_fd, "#TZ/UNKNOWN\n"); +#ifdef CONFIG_RTC + fdprintf(scrobbler_fd, "#CLIENT/Rockbox %s %s\n", + TARGET_NAME, SCROBBLER_REVISION); +#else + fdprintf(scrobbler_fd, "#CLIENT/Rockbox %s %s Timeless\n", + TARGET_NAME, SCROBBLER_REVISION); +#endif + close(scrobbler_fd); + } + else + { + logf("SCROBBLER: cannot create log file"); + } + } + close(scrobbler_fd); + scrobbler_fd = -1; + + /* write the cache entries */ + scrobbler_fd = open(SCROBBLER_FILE, O_WRONLY | O_APPEND); + if(scrobbler_fd >= 0) + { + logf("SCROBBLER: writing %d entries", cache_pos); + + for ( i=0; i < cache_pos; i++ ) + { + logf("SCROBBLER: write %d", i); + fdprintf(scrobbler_fd, "%s", scrobbler_cache+(SCROBBLER_CACHE_LEN*i)); + } + close(scrobbler_fd); + } + else + { + logf("SCROBBLER: error writing file"); + } + + /* clear even if unsuccessful - don't want to overflow the buffer */ + cache_pos = 0; + scrobbler_fd = -1; +} + +static void add_to_cache(void) +{ +/* using HAVE_MMC to check for Ondios - anything better to use? */ +#ifndef SIMULATOR +#if defined(IPOD_NANO) || defined(HAVE_MMC) + if ( cache_pos >= SCROBBLER_MAX_CACHE ) +#else + if ( ( cache_pos >= SCROBBLER_MAX_CACHE ) || ( ata_disk_is_active() ) ) +#endif +#endif /* !SIMULATOR */ + write_cache(); + + int ret; + char rating = 'S'; /* Skipped */ + + logf("SCROBBLER: add_to_cache[%d]", cache_pos); + + if ( audio_prev_elapsed() > + (scrobbler_entry.length/2) ) + rating = 'L'; /* Listened */ + + if (scrobbler_entry.tracknum > 0) + { + ret = snprintf(scrobbler_cache+(SCROBBLER_CACHE_LEN*cache_pos), + SCROBBLER_CACHE_LEN, + "%s\t%s\t%s\t%d\t%d\t%c\t%ld\n", + scrobbler_entry.artist, + scrobbler_entry.album?scrobbler_entry.album:"", + scrobbler_entry.title, + scrobbler_entry.tracknum, + (int)scrobbler_entry.length/1000, + rating, + (long)timestamp); + } else { + ret = snprintf(scrobbler_cache+(SCROBBLER_CACHE_LEN*cache_pos), + SCROBBLER_CACHE_LEN, + "%s\t%s\t%s\t\t%d\t%c\t%ld\n", + scrobbler_entry.artist, + scrobbler_entry.album?scrobbler_entry.album:"", + scrobbler_entry.title, + (int)scrobbler_entry.length/1000, + rating, + (long)timestamp); + } + + if ( ret >= SCROBBLER_CACHE_LEN ) + { + logf("SCROBBLER: entry too long:"); + logf("SCROBBLER: %s", scrobbler_entry.path); + } else + cache_pos++; +} + +void scrobbler_change_event(struct mp3entry *id) +{ + /* add entry using the previous scrobbler_entry and timestamp */ + if (pending) + add_to_cache(); + + /* check if track was resumed > %50 played + check for blank artist or track name */ + if ((id->elapsed > (id->length/2)) || + (!id->artist ) || (!id->title ) ) + { + pending = false; + logf("SCROBBLER: skipping file %s", id->path); + } + else + { + logf("SCROBBLER: add pending"); + copy_mp3entry(&scrobbler_entry, id); +#ifdef CONFIG_RTC + timestamp = mktime(get_time()); +#else + timestamp = 0; +#endif + pending = true; + } +} + +int scrobbler_init(void) +{ + logf("SCROBBLER: init %d", global_settings.audioscrobbler); + + if(!global_settings.audioscrobbler) + return -1; + + scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN); + + audio_set_track_changed_event(&scrobbler_change_event); + cache_pos = 0; + pending = false; + scrobbler_initialised = true; + + return 1; +} + +void scrobbler_flush_cache(void) +{ + if (scrobbler_initialised) + { + /* Add any pending entries to the cache */ + if(pending) + add_to_cache(); + + /* Write the cache to disk if needed */ + if (cache_pos) + write_cache(); + + pending = false; + } +} + +void scrobbler_shutdown(void) +{ + scrobbler_flush_cache(); + + if (scrobbler_initialised) + { + audio_set_track_changed_event(NULL); + scrobbler_initialised = false; + } +} + +bool scrobbler_is_enabled(void) +{ + return scrobbler_initialised; +} |