--- xmms-1.2.10.orig/libxmms/configfile.c 2003-05-19 23:22:07.000000000 +0200 +++ xmms-1.2.10/libxmms/configfile.c 2006-07-07 12:07:37.000000000 +0200 @@ -43,15 +43,15 @@ ConfigFile *xmms_cfg_new(void) return cfg; } -ConfigFile *xmms_cfg_open_file(gchar * filename) +static +ConfigFile *xmms_cfg_open_or_merge_file(ConfigFile *cfg, gchar * filename) { - ConfigFile *cfg; - FILE *file; char *buffer, **lines, *tmp; int i; struct stat stats; ConfigSection *section = NULL; + ConfigLine *line; g_return_val_if_fail(filename != NULL, FALSE); @@ -70,7 +70,9 @@ ConfigFile *xmms_cfg_open_file(gchar * f fclose(file); buffer[stats.st_size] = '\0'; - cfg = g_malloc0(sizeof (ConfigFile)); + if (!cfg) + cfg = g_malloc0(sizeof (ConfigFile)); + lines = g_strsplit(buffer, "\n", 0); g_free(buffer); i = 0; @@ -81,7 +83,9 @@ ConfigFile *xmms_cfg_open_file(gchar * f if ((tmp = strchr(lines[i], ']'))) { *tmp = '\0'; - section = xmms_cfg_create_section(cfg, &lines[i][1]); + section = xmms_cfg_find_section(cfg, &lines[i][1]); + if (!section) + section = xmms_cfg_create_section(cfg, &lines[i][1]); } } else if (lines[i][0] != '#' && section) @@ -90,7 +94,13 @@ ConfigFile *xmms_cfg_open_file(gchar * f { *tmp = '\0'; tmp++; - xmms_cfg_create_string(section, lines[i], tmp); + if ((line = xmms_cfg_find_string(section, lines[i]))) + { + g_free(line->value); + line->value = g_strchug(g_strchomp(g_strdup(tmp))); + } + else + xmms_cfg_create_string(section, lines[i], tmp); } } i++; @@ -99,6 +109,20 @@ ConfigFile *xmms_cfg_open_file(gchar * f return cfg; } +static gchar *custom_filename = NULL; +ConfigFile *xmms_cfg_open_file(gchar *filename) +{ + ConfigFile *cfg = xmms_cfg_open_or_merge_file(NULL, filename); + if (cfg && custom_filename) + xmms_cfg_open_or_merge_file(cfg, custom_filename); + return cfg; +} + +void xmms_cfg_set_custom_filename(gchar *filename) +{ + custom_filename = filename; +} + gchar * xmms_cfg_get_default_filename(void) { static char *filename = NULL; --- xmms-1.2.10.orig/libxmms/configfile.h 2000-02-16 22:05:54.000000000 +0100 +++ xmms-1.2.10/libxmms/configfile.h 2006-07-07 12:07:37.000000000 +0200 @@ -65,6 +65,8 @@ void xmms_cfg_write_double(ConfigFile * void xmms_cfg_remove_key(ConfigFile * cfg, gchar * section, gchar * key); +void xmms_cfg_set_custom_filename(gchar *filename); + #ifdef __cplusplus }; #endif --- xmms-1.2.10.orig/xmms/controlsocket.c 2004-02-23 21:31:43.000000000 +0100 +++ xmms-1.2.10/xmms/controlsocket.c 2006-07-07 12:07:37.000000000 +0200 @@ -50,13 +50,18 @@ static pthread_cond_t start_cond = PTHRE gboolean setup_ctrlsocket(void) { + return setup_ctrlsocket_internal(-1); +} + +gboolean setup_ctrlsocket_internal(gint session_id) +{ struct sockaddr_un saddr; gboolean retval = FALSE; gint i; if ((ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) { - for (i = 0;; i++) + for (i = ((session_id >= 0) ? session_id : 0); (session_id < 0 || i == session_id); i++) { saddr.sun_family = AF_UNIX; g_snprintf(saddr.sun_path, 108, "%s/xmms_%s.%d", @@ -72,10 +77,17 @@ gboolean setup_ctrlsocket(void) } else { + if (session_id >= 0 && session_id != i) + { + g_log(NULL, G_LOG_LEVEL_CRITICAL, + "setup_ctrlsocket(): Session %d already running!", session_id); + break; + } if (cfg.allow_multiple_instances) continue; break; } + if (bind(ctrl_fd, (struct sockaddr *) &saddr, sizeof (saddr)) != -1) { session_id = i; @@ -95,6 +107,7 @@ gboolean setup_ctrlsocket(void) break; } } + } else g_log(NULL, G_LOG_LEVEL_CRITICAL, --- xmms-1.2.10.orig/xmms/controlsocket.h 2003-06-11 20:44:17.000000000 +0200 +++ xmms-1.2.10/xmms/controlsocket.h 2006-07-07 12:07:37.000000000 +0200 @@ -23,6 +23,7 @@ #define XMMS_PROTOCOL_VERSION 1 gboolean setup_ctrlsocket(void); +gboolean setup_ctrlsocket_internal(gint session_id); void cleanup_ctrlsocket(void); void start_ctrlsocket(void); void check_ctrlsocket(void); --- xmms-1.2.10.orig/xmms/input.c 2003-08-08 19:10:44.000000000 +0200 +++ xmms-1.2.10/xmms/input.c 2006-07-07 12:07:37.000000000 +0200 @@ -285,6 +285,14 @@ void input_seek(int time) } } +gboolean input_stopped_for_restart = FALSE; /* crossfade */ +void input_stop_for_restart() /* crossfade */ +{ + input_stopped_for_restart = TRUE; + input_stop(); + input_stopped_for_restart = FALSE; +} + void input_stop(void) { if (ip_data->playing && get_current_input_plugin()) --- xmms-1.2.10.orig/xmms/input.h 2000-02-16 22:05:57.000000000 +0100 +++ xmms-1.2.10/xmms/input.h 2006-07-07 12:07:37.000000000 +0200 @@ -34,6 +34,7 @@ InputVisType input_get_vis_type(); gboolean input_check_file(gchar * filename); void input_play(char *filename); void input_stop(void); +void input_stop_for_restart(void); void input_pause(void); int input_get_time(void); void input_set_eq(int on, float preamp, float *bands); --- xmms-1.2.10.orig/xmms/main.c 2004-02-23 21:31:43.000000000 +0100 +++ xmms-1.2.10/xmms/main.c 2006-07-07 12:08:22.000000000 +0200 @@ -1,3 +1,4 @@ + /* XMMS - Cross-platform multimedia player * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, * Thomas Nilsson and 4Front Technologies @@ -881,8 +882,10 @@ void mainwin_shade_toggle(void) mainwin_set_shade(!cfg.player_shaded); } +gboolean is_quitting = FALSE; /* crossfade */ void mainwin_quit_cb(void) { + is_quitting = TRUE; /* crossfade */ input_stop(); gtk_widget_hide(equalizerwin); gtk_widget_hide(playlistwin); @@ -1523,7 +1526,8 @@ static void mainwin_jump_to_file_real_cb int *pos; if (get_input_playing()) - input_stop(); + input_stop_for_restart(); + pos = gtk_clist_get_row_data(clist, GPOINTER_TO_INT(clist->selection->data)); playlist_set_position(*pos); playlist_play(); @@ -3202,6 +3206,7 @@ static struct option long_options[] = { {"help", 0, NULL, 'h'}, {"session", 1, NULL, 'n'}, + {"force-session", 0, NULL, 'N' }, {"rew", 0, NULL, 'r'}, {"play", 0, NULL, 'p'}, {"pause", 0, NULL, 'u'}, @@ -3212,6 +3217,7 @@ static struct option long_options[] = {"show-main-window", 0, NULL, 'm'}, {"version", 0, NULL, 'v'}, {"sm-client-id", 1, NULL, 'i'}, + {"config", 1, NULL, 'c'}, {0, 0, 0, 0} }; @@ -3224,8 +3230,11 @@ void display_usage(void) /* -h, --help switch */ fprintf(stderr, _("Display this text and exit.")); fprintf(stderr, "\n-n, --session "); - /* -n, --session switch */ + /* -n, --session option */ fprintf(stderr, _("Select XMMS session (Default: 0)")); + fprintf(stderr, "\n-N, --force-session "); + /* -N, -force-session switch */ + fprintf(stderr, _("Force XMMS session")); fprintf(stderr, "\n-r, --rew "); /* -r, --rew switch */ fprintf(stderr, _("Skip backwards in playlist")); @@ -3263,6 +3272,7 @@ void display_usage(void) struct cmdlineopt { GList *filenames; int session; + gboolean force_session; gboolean play, stop, pause, fwd, rew, play_pause; gboolean enqueue, mainwin, remote; char *previous_session_id; @@ -3275,7 +3285,8 @@ void parse_cmd_line(int argc, char **arg memset(opt, 0, sizeof(struct cmdlineopt)); opt->session = -1; - while ((c = getopt_long(argc, argv, "hn:rpusfemvt", long_options, NULL)) != -1) + opt->force_session = FALSE; + while ((c = getopt_long(argc, argv, "hn:rpusfemvtNC", long_options, NULL)) != -1) { switch (c) { @@ -3285,6 +3296,12 @@ void parse_cmd_line(int argc, char **arg case 'n': opt->session = atoi(optarg); break; + case 'c': + xmms_cfg_set_custom_filename(g_strdup(optarg)); + break; + case 'N': + opt->force_session = TRUE; + break; case 'r': opt->rew = TRUE; break; @@ -3557,7 +3574,9 @@ int main(int argc, char **argv) } make_xmms_dir(); - if (options.session != -1 || !setup_ctrlsocket()) + if (options.force_session + ? !setup_ctrlsocket_internal(options.session) + : (options.session != -1 || !setup_ctrlsocket())) { handle_cmd_line_options(&options, TRUE); exit(0); --- xmms-1.2.10.orig/xmms/playlist.c 2004-02-23 21:31:43.000000000 +0100 +++ xmms-1.2.10/xmms/playlist.c 2006-07-07 12:07:37.000000000 +0200 @@ -39,7 +39,7 @@ extern SVis *mainwin_svis; static gboolean playlist_get_info_entry(PlaylistEntry *entry); static int playlist_sort_str_by_path_cmpfunc(gconstpointer a, gconstpointer b); static guint playlist_load_ins(char * filename, long pos); -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, char *fade); static int __get_playlist_length(void); static void playlist_generate_shuffle_list(void); static void __playlist_generate_shuffle_list(void); @@ -77,9 +77,10 @@ void playlist_clear(void) { GList *node; PlaylistEntry *entry; - - if (get_input_playing()) - input_stop(); + + /* always assume that there is another song comming up */ + if (get_input_playing()) + input_stop_for_restart(); pthread_mutex_lock(&playlist_mutex); if (playlist) @@ -88,10 +89,9 @@ void playlist_clear(void) while (node) { entry = node->data; - if (entry->filename) - g_free(entry->filename); - if (entry->title) - g_free(entry->title); + g_free(entry->filename); + g_free(entry->title); + g_free(entry->fade); g_free(entry); node = node->next; } @@ -124,7 +124,7 @@ void playlist_delete_node(GList *node, g if (get_input_playing()) { PL_UNLOCK(); - input_stop(); + input_stop_for_restart(); PL_LOCK(); *restart_playing = TRUE; } @@ -150,10 +150,9 @@ void playlist_delete_node(GList *node, g g_list_free_1(queued_song); } - if (entry->filename) - g_free(entry->filename); - if (entry->title) - g_free(entry->title); + g_free(entry->filename); + g_free(entry->title); + g_free(entry->fade); shuffle_list = g_list_remove(shuffle_list, entry); playlist = g_list_remove_link(playlist, node); g_free(entry); @@ -262,15 +261,15 @@ void playlist_delete(gboolean crop) } } -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, char *fade) { PlaylistEntry *entry; entry = g_malloc0(sizeof (PlaylistEntry)); entry->filename = g_strdup(filename); - if (title) - entry->title = g_strdup(title); - entry->length = len; + entry->title = g_strdup(title); + entry->length = len; + entry->fade = g_strdup(fade); pthread_mutex_lock(&playlist_mutex); playlist = g_list_insert(playlist, entry, pos); @@ -279,9 +278,9 @@ static void __playlist_ins_with_info(cha playlist_get_info_scan_active = TRUE; } -static void __playlist_ins(char * filename, long pos) +static void __playlist_ins(char *filename, long pos) { - __playlist_ins_with_info(filename, pos, NULL, -1); + __playlist_ins_with_info(filename, pos, NULL, -1, NULL); } static gboolean is_playlist_name(char *pathname) @@ -570,7 +569,7 @@ void playlist_play(void) } if (get_input_playing()) - input_stop(); + input_stop_for_restart(); vis_clear_data(mainwin_vis); vis_clear_data(playlistwin_vis); @@ -668,7 +667,7 @@ void playlist_next(void) { /* We need to stop before changing playlist_position */ PL_UNLOCK(); - input_stop(); + input_stop_for_restart(); PL_LOCK(); restart_playing = TRUE; } @@ -723,7 +722,7 @@ void playlist_prev(void) { /* We need to stop before changing playlist_position */ PL_UNLOCK(); - input_stop(); + input_stop_for_restart(); PL_LOCK(); restart_playing = TRUE; } @@ -852,7 +851,7 @@ void playlist_set_position(int pos) { /* We need to stop before changing playlist_position */ PL_UNLOCK(); - input_stop(); + input_stop_for_restart(); PL_LOCK(); restart_playing = TRUE; } @@ -879,11 +878,25 @@ void playlist_set_position(int pos) void playlist_eof_reached(void) { GList *plist_pos_list; - - input_stop(); + gboolean stop_for_restart = TRUE; PL_LOCK(); + + /* + * First, determine if we are going to play another song after + * this one and call input_stop() / input_stop_for_restart() + * accordingly. + */ plist_pos_list = find_playlist_position_list(); + if (!queued_list && !g_list_next(plist_pos_list) && !cfg.repeat) + stop_for_restart = FALSE; + + PL_UNLOCK(); + if (stop_for_restart) + input_stop_for_restart(); + else + input_stop(); + PL_LOCK(); if (cfg.no_playlist_advance) { @@ -1060,7 +1073,7 @@ gboolean playlist_load(char * filename) 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, char *fade) { char *temp, *path; @@ -1080,16 +1093,16 @@ static void playlist_load_ins_file(char *temp = '\0'; else { - __playlist_ins_with_info(filename, pos, title, len); + __playlist_ins_with_info(filename, pos, title, len, fade); 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, fade); g_free(temp); g_free(path); } else - __playlist_ins_with_info(filename, pos, title, len); + __playlist_ins_with_info(filename, pos, title, len, fade); } static void parse_extm3u_info(char *info, char **title, int *length) @@ -1128,7 +1141,7 @@ static guint playlist_load_ins(char * fi guint entries = 0; int linelen = 1024; gboolean extm3u = FALSE; - char *ext_info = NULL, *ext_title = NULL; + char *ext_info = NULL, *ext_title = NULL, *ext_fade = NULL; int ext_len = -1; ext = strrchr(filename, '.'); @@ -1152,7 +1165,7 @@ static guint playlist_load_ins(char * fi if (line != NULL) { playlist_load_ins_file(line, filename, pos, - NULL, -1); + NULL, -1, NULL); entries++; if (pos >= 0) pos++; @@ -1200,6 +1213,13 @@ static guint playlist_load_ins(char * fi ext_info = g_strdup(line); continue; } + else if (extm3u && !strncmp(line, "#EXTFADE:", 9)) + { + if (ext_fade) + g_free(ext_fade); + ext_fade = g_strdup(line); + continue; + } if (line[0] == '#') { @@ -1219,11 +1239,14 @@ static guint playlist_load_ins(char * fi 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_fade); g_free(ext_title); ext_title = NULL; ext_len = -1; + + g_free(ext_fade); + ext_fade = NULL; entries++; if (pos >= 0) @@ -1367,6 +1390,32 @@ int playlist_get_songtime(int pos) return retval; } +char * playlist_get_fadeinfo(int pos) +{ + char *ret; + PlaylistEntry *entry; + GList *node; + + PL_LOCK(); + if (!playlist) + { + PL_UNLOCK(); + return NULL; + } + node = g_list_nth(playlist, pos); + if (!node) + { + PL_UNLOCK(); + return NULL; + } + entry = node->data; + + ret = g_strdup(entry->fade); + PL_UNLOCK(); + + return ret; +} + static int playlist_sort_by_title_cmpfunc(PlaylistEntry * a, PlaylistEntry * b) { char *a_title, *b_title; --- xmms-1.2.10.orig/xmms/playlist.h 2004-01-17 01:22:17.000000000 +0100 +++ xmms-1.2.10/xmms/playlist.h 2006-07-07 12:07:37.000000000 +0200 @@ -26,6 +26,7 @@ typedef struct gchar *title; gint length; gboolean selected; + gchar *fade; } PlaylistEntry;