/* vim:syntax=c tabstop=2 shiftwidth=2 noexpandtab Shell.FM - interface.c Copyright (C) 2006 by Jonas Kramer Copyright (C) 2006 by Bart Trojanowski Published under the terms of the GNU General Public License (GPLv2). */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "completion.h" #include "http.h" #include "settings.h" #include "readline.h" #include "history.h" #include "split.h" #include "feeds.h" #include "strary.h" #include "service.h" #include "tag.h" extern char ** popular; static int radiocomplete(char *, const unsigned, int); static char ** users = NULL, ** artists = NULL, ** overall = NULL; /* * This function is called to change the station * the user is prompted for the new radio station. * * Something like: * * lastfm://user/BartTrojanowski/loved * lastfm://user/BartTrojanowski/personal * lastfm://user/BartTrojanowski/neighbour * lastfm://user/BartTrojanowski/recommended/100 * lastfm://usertags/BartTrojanowski/trance * lastfm://artist/QED/similarartists * lastfm://artist/QED/fans * lastfm://globaltags/goa * lastfm://globaltags/classical,miles davis,whatever * lastfm://multipleartists/QED,Chicane * lastfm://play/tracks/########[,#####, ...] */ void radioprompt(const char * prompt) { char * url, * decoded = NULL; struct prompt setup = { .prompt = prompt, .line = NULL, .history = uniq(slurp(rcpath("radio-history"))), .callback = radiocomplete, }; /* Get overall top tags. */ overall = overalltags(); /* Get user, friends and neighbors. */ users = neighbors(value(& rc, "username")); users = merge(users, friends(value(& rc, "username")), 0); users = append(users, value(& rc, "username")); /* Get top artists. */ artists = topartists(value(& rc, "username")); /* Read the line. */ url = readline(& setup); /* Free everything. */ purge(users); purge(artists); purge(overall); overall = users = artists = NULL; if(setup.history) purge(setup.history); if(strlen(url)) { decode(url, & decoded); station(decoded); free(decoded); } } int radiocomplete(char * line, const unsigned max, int changed) { unsigned length = strlen(line), nsplt = 0, slash = 0, nres = 0; const char * match; char ** splt, * types [] = { "user", "usertags", "artist", "globaltags", "play", NULL }; if(!strncasecmp(line, "lastfm://", 9)) { memmove(line, line + 9, 9); memset(line + 9, 0, max - (length -= 9)); } if(length > 0 && line[length - 1] == '/') { slash = !0; changed = !0; } splt = split(line, "/", & nsplt); if(!nsplt) { free(splt); return 0; } switch(nsplt + slash) { /* First level completions (user, usertags, artists, ...) */ case 1: if((match = nextmatch(types, changed ? splt[0] : NULL, & nres)) != NULL) snprintf(line, max, "%s%s", match, nres == 1 ? "/" : ""); break; /* Second level completions (user/$USER, globaltags/$TAG, ...) */ case 2: if(!strcmp(splt[0], "user") || !strcmp(splt[0], "usertags")) { match = nextmatch(users, changed ? (slash ? "" : splt[1]) : NULL, & nres); if(match) snprintf(line, max, "%s/%s%s", splt[0], match, nres == 1 ? "/" : ""); } else if(!strcmp(splt[0], "artist")) { match = nextmatch(artists, changed ? (slash ? "" : splt[1]) : NULL, & nres); if(match) snprintf(line, max, "%s/%s%s", splt[0], match, nres == 1 ? "/" : ""); } else if(!strcmp(splt[0], "globaltags")) { char * lastchunk = strrchr(line, '/') + 1; popular = overalltags(); tagcomplete(lastchunk, max - (lastchunk - line), changed); purge(popular); } break; /* Third level completions (artist/$ARTIST/fans, ...) */ case 3: if(!strcmp(splt[0], "user")) { char * radios [] = { "personal", "neighbours", "loved", "recommended", "playlist", NULL }; match = nextmatch(radios, changed ? (slash ? "" : splt[2]) : NULL, NULL); snprintf(line, max, "%s/%s/%s", splt[0], splt[1], match ? match : splt[2]); } else if(!strcmp(splt[0], "artist")) { char * radios [] = { "fans", "similarartists", NULL }; match = nextmatch(radios, changed ? (slash ? "" : splt[2]) : NULL, NULL); snprintf(line, max, "%s/%s/%s", splt[0], splt[1], match ? match : splt[2]); } else if(!strcmp(splt[0], "usertags")) { char * lastchunk = strrchr(line, '/') + 1; popular = overalltags(); tagcomplete(lastchunk, max - (lastchunk - line), changed); purge(popular); } break; } while(nsplt--) free(splt[nsplt]); free(splt); return !0; }