diff -u xmms-cvs/xmms/main.c xmms/xmms/main.c --- xmms-cvs/xmms/main.c Fri Apr 26 11:41:18 2002 +++ xmms/xmms/main.c Fri Apr 26 12:14:40 2002 @@ -346,7 +346,7 @@ cfg.random_skin_on_play = FALSE; cfg.mainwin_use_xfont = FALSE; cfg.read_pl_metadata = TRUE; - + cfg.use_scoring = FALSE; cfg.playlist_x = 295; cfg.playlist_y = 20; cfg.playlist_width = 300; @@ -397,6 +397,7 @@ xmms_cfg_read_boolean(cfgfile, "xmms", "no_playlist_advance", &cfg.no_playlist_advance); xmms_cfg_read_boolean(cfgfile, "xmms", "sort_jump_to_file", &cfg.sort_jump_to_file); xmms_cfg_read_boolean(cfgfile, "xmms", "read_pl_metadata", &cfg.read_pl_metadata); + xmms_cfg_read_boolean(cfgfile, "xmms", "use_scoring", &cfg.use_scoring); xmms_cfg_read_boolean(cfgfile, "xmms", "smooth_title_scroll", &cfg.smooth_title_scroll); xmms_cfg_read_boolean(cfgfile, "xmms", "use_backslash_as_dir_delimiter", &cfg.use_backslash_as_dir_delimiter); xmms_cfg_read_int(cfgfile, "xmms", "player_x", &cfg.player_x); @@ -556,6 +557,7 @@ xmms_cfg_write_boolean(cfgfile, "xmms", "save_window_positions", cfg.save_window_position); xmms_cfg_write_boolean(cfgfile, "xmms", "dim_titlebar", cfg.dim_titlebar); xmms_cfg_write_boolean(cfgfile, "xmms", "read_pl_metadata", cfg.read_pl_metadata); + xmms_cfg_write_boolean(cfgfile, "xmms", "use_scoring", cfg.use_scoring); xmms_cfg_write_boolean(cfgfile, "xmms", "get_info_on_load", cfg.get_info_on_load); xmms_cfg_write_boolean(cfgfile, "xmms", "get_info_on_demand", cfg.get_info_on_demand); xmms_cfg_write_boolean(cfgfile, "xmms", "eq_doublesize_linked", cfg.eq_doublesize_linked); @@ -677,6 +679,11 @@ g_free(filename); filename = g_strconcat(g_get_home_dir(), "/.xmms/xmms.m3u", NULL); playlist_save(filename); + + /* re-random playlist in case use_scoring has changed */ + if (mainwin_shuffle->tb_selected) + playlist_generate_shuffle_list(); + g_free(filename); } diff -u xmms-cvs/xmms/main.h xmms/xmms/main.h --- xmms-cvs/xmms/main.h Fri Apr 26 11:41:18 2002 +++ xmms/xmms/main.h Fri Apr 26 11:52:40 2002 @@ -60,6 +60,7 @@ gint mouse_change; gboolean playlist_transparent; gchar *gentitle_format; + gboolean use_scoring; } Config; diff -u xmms-cvs/xmms/playlist.c xmms/xmms/playlist.c --- xmms-cvs/xmms/playlist.c Fri Apr 26 11:41:18 2002 +++ xmms/xmms/playlist.c Fri Apr 26 12:17:56 2002 @@ -22,7 +22,7 @@ #include "libxmms/util.h" #include #include - +#include GList *playlist = NULL; GList *shuffle_list = NULL; static gboolean playlist_get_info_scan_active = FALSE; @@ -219,7 +219,7 @@ } } -static void __playlist_ins_with_info(char *filename, long pos, char* title, int len) +static void __playlist_ins_with_info(char *filename, long pos, char* title, int len, int score) { PlaylistEntry *entry; @@ -228,7 +228,7 @@ if (title) entry->title = g_strdup(title); entry->length = len; - + entry->score = score; pthread_mutex_lock(&playlist_mutex); playlist = g_list_insert(playlist, entry, pos); pthread_mutex_unlock(&playlist_mutex); @@ -238,7 +238,7 @@ static void __playlist_ins(char * filename, long pos) { - __playlist_ins_with_info(filename, pos, NULL, -1); + __playlist_ins_with_info(filename, pos, NULL, -1, 0); } static gboolean is_playlist_name(char *pathname) @@ -534,7 +534,6 @@ { GList *plist_pos_list; gboolean restart_playing = FALSE; - PL_LOCK(); if (!playlist) { @@ -543,7 +542,9 @@ } plist_pos_list = find_playlist_position_list(); - + if (cfg.shuffle) { + playlist_score_file(-1); + } if (!cfg.repeat && !g_list_next(plist_pos_list)) { PL_UNLOCK(); @@ -598,7 +599,9 @@ } plist_pos_list = find_playlist_position_list(); - + if (cfg.shuffle) { + playlist_score_file(-1); + } if (!cfg.repeat && !g_list_previous(plist_pos_list)) { PL_UNLOCK(); @@ -648,6 +651,7 @@ GList *node; gboolean restart_playing = FALSE; + playlist_score_file(-1); PL_LOCK(); if (!playlist) { @@ -682,6 +686,18 @@ mainwin_set_info_text(); playlistwin_update_list(); } + playlist_score_file(+1); +} + +void playlist_score_file(gint factor) +{ + if(!get_input_playing() && factor==-1) { + return; + } + if(playlist_position->score < -19 || playlist_position->score > 19) { + return; + } + playlist_position->score += factor; } void playlist_eof_reached(void) @@ -857,8 +873,8 @@ else seconds = -1; - fprintf(file, "#EXTINF:%d,%s\n", - seconds, entry->title); + fprintf(file, "#EXTINF:%d,%s,%d\n", + seconds, entry->title,entry->score); } fprintf(file, "%s\n", entry->filename); } @@ -874,7 +890,7 @@ return playlist_load_ins(filename, -1); } -static void playlist_load_ins_file(char *filename, char *playlist_name, long pos, char *title, int len) +static void playlist_load_ins_file(char *filename, char *playlist_name, long pos, char *title, int len, int score) { gchar *temp, *path; @@ -894,25 +910,25 @@ *temp = '\0'; else { - __playlist_ins_with_info(filename, pos, title, len); + __playlist_ins_with_info(filename, pos, title, len, score); return; } temp = g_strdup_printf("%s/%s", path, filename); - __playlist_ins_with_info(temp, pos, title, len); + __playlist_ins_with_info(temp, pos, title, len, score); g_free(temp); g_free(path); } else - __playlist_ins_with_info(filename, pos, title, len); + __playlist_ins_with_info(filename, pos, title, len, score); } -static void parse_ext3u_info(char *info, char **title, int *length) +static void parse_ext3u_info(char *info, char **title, int *length, int *score) { char *str; - + char *str_score; *title = NULL; *length = -1; - + *score = 0; if (!info) return; @@ -926,6 +942,12 @@ if ((str = strchr(info, ',')) != NULL) { *title = g_strdup(str + 1); + if(str!= (str_score = strrchr(info, ','))){ + if(str_score != NULL) { + *title = g_strndup(*title, strlen(*title)-strlen(str_score)); + } + } + g_strstrip(*title); if (strlen(*title) < 1) { @@ -933,6 +955,11 @@ *title = NULL; } } + if(str != NULL && str!= (str_score = strrchr(info, ','))) { + if(str_score != NULL) { + *score = atoi(str_score+1); + } + } } guint playlist_load_ins(gchar * filename, glong pos) @@ -943,7 +970,7 @@ int linelen = 1024; gboolean extm3u = FALSE; char *ext_info = NULL, *ext_title = NULL; - int ext_len = -1; + int ext_len = -1, ext_score = 0; ext = strrchr(filename, '.'); if (ext && !strcasecmp(ext, ".pls")) @@ -965,7 +992,7 @@ if (line != NULL) { playlist_load_ins_file(line, filename, pos, - NULL, -1); + NULL, -1, 0); entries++; if (pos >= 0) pos++; @@ -1027,16 +1054,17 @@ if (extm3u) { if (cfg.read_pl_metadata) - parse_ext3u_info(ext_info, &ext_title, &ext_len); + parse_ext3u_info(ext_info, &ext_title, &ext_len, &ext_score); g_free(ext_info); ext_info = NULL; } - playlist_load_ins_file(line, filename, pos, ext_title, ext_len); + playlist_load_ins_file(line, filename, pos, ext_title, ext_len, ext_score); g_free(ext_title); ext_title = NULL; ext_len = -1; + ext_score = 0; entries++; if (pos >= 0) @@ -1363,6 +1391,18 @@ PL_UNLOCK(); } +static int sort_score(const void *a, const void *b) +{ + + int score_a = (*((PlaylistEntry **)a))->score; + int score_b = (*((PlaylistEntry **)b))->score; + + /* We want high scores before low, so if score_a > score_b we + want to return something negative. */ + + return score_b - score_a; +} + static GList *playlist_shuffle_list(GList *list) { /* Caller should holde playlist mutex */ @@ -1403,11 +1443,104 @@ return list; } +static GList *playlist_shuffle_list_with_score(GList *list) +{ + /* Caller should holde playlist mutex */ + /* + * Note that this doesn't make a copy of the original list. + * The pointer to the original list is not valid after this + * fuction is run. + */ + gint len = g_list_length(list); + gint i, next_score_section=-1; + GList *current_node; + PlaylistEntry **entries; + + if (len==0) + return NULL; + + entries = g_new(PlaylistEntry *, len); + for (current_node = list, i = 0; i < len; current_node = g_list_next(current_node), i++) + { + entries[i] = (PlaylistEntry *)(current_node->data); + } + g_list_free(list); + list = NULL; + + /* Sort by score */ + qsort(entries, len, sizeof(PlaylistEntry *), sort_score); + + /* Shuffle */ + for (i = 0; i < len; i++) + { + PlaylistEntry *temp_entry; + gint j; + + if (i >= next_score_section) + { + gint current_score = entries[i]->score; + + for (next_score_section = i; next_score_section < len; next_score_section++) + { + if (entries[next_score_section]->score != current_score) + { + break; + } + } + } + + /* Find out from which index we should get the next song */ + do { + j = (rand() % (next_score_section - i)) + i; + + assert(j < next_score_section); + } while (j == -1); + + assert(j < len); + assert(j >= i); + + if (j < next_score_section) + { + /* Swap pointer #i and pointer #j */ + temp_entry = entries[i]; + entries[i] = entries[j]; + entries[j] = temp_entry; + temp_entry = NULL; + } + else + { + gint k; + + temp_entry = entries[i]; + entries[i] = entries[j]; + + for (k = j; k >= (i + 2); k--) + { + entries[k] = entries[k - 1]; + } + + entries[i + 1] = temp_entry; + } + } + + /* Create new list */ + for (i = 0; i < len; i++) + { + list = g_list_append(list, entries[i]); + } + + g_free(entries); + + return list; +} + void playlist_random(void) { PL_LOCK(); - - playlist = playlist_shuffle_list(playlist); + if (cfg.use_scoring) + playlist = playlist_shuffle_list_with_score(playlist); + else + playlist = playlist_shuffle_list(playlist); PL_UNLOCK(); } @@ -1445,7 +1578,10 @@ } if (playlist) { - shuffle_list = playlist_shuffle_list(g_list_copy(playlist)); + if (cfg.use_scoring) + shuffle_list = playlist_shuffle_list_with_score(g_list_copy(playlist)); + else + shuffle_list = playlist_shuffle_list(g_list_copy(playlist)); numsongs = g_list_length(shuffle_list); if (!numsongs) diff -u xmms-cvs/xmms/playlist.h xmms/xmms/playlist.h --- xmms-cvs/xmms/playlist.h Fri Apr 26 11:41:18 2002 +++ xmms/xmms/playlist.h Fri Apr 26 11:42:14 2002 @@ -26,6 +26,7 @@ gchar *title; gint length; gboolean selected; + gint score; } PlaylistEntry; @@ -47,6 +48,7 @@ void playlist_prev(void); void playlist_eof_reached(void); void playlist_set_position(gint pos); +void playlist_score_file(gint factor); gint get_playlist_length(void); gint __get_playlist_length(void); gint get_playlist_position(void); diff -u xmms-cvs/xmms/prefswin.c xmms/xmms/prefswin.c --- xmms-cvs/xmms/prefswin.c Fri Apr 26 11:41:18 2002 +++ xmms/xmms/prefswin.c Fri Apr 26 11:51:22 2002 @@ -996,6 +996,7 @@ gtk_table_attach_defaults(GTK_TABLE(options_table), options_mouse_box, 0, 1, 8, 9); prefswin_option_new_with_label_to_table(&cfg.read_pl_metadata, _("Read meta data from playlists"), GTK_TABLE(options_table), 1, 8); + prefswin_option_new_with_label_to_table(&cfg.use_scoring, _("Score random playing"), GTK_TABLE(options_table), 0, 10); gtk_notebook_append_page(GTK_NOTEBOOK(prefswin_notebook), prefswin_options_vbox, gtk_label_new(_("Options")));