📄 playlist.c
字号:
gboolean restart_playing = FALSE; PL_LOCK(); if (!playlist) { PL_UNLOCK(); return; } plist_pos_list = find_playlist_position_list(); if (!cfg.repeat && !g_list_previous(plist_pos_list)) { PL_UNLOCK(); return; } if (get_input_playing()) { /* We need to stop before changing playlist_position */ PL_UNLOCK(); input_stop(); PL_LOCK(); restart_playing = TRUE; } plist_pos_list = find_playlist_position_list(); if (g_list_previous(plist_pos_list)) playlist_position = plist_pos_list->prev->data; else if (cfg.repeat) { GList *node; playlist_position = NULL; __playlist_generate_shuffle_list(); if (cfg.shuffle) node = g_list_last(shuffle_list); else node = g_list_last(playlist); if (node) playlist_position = node->data; } PL_UNLOCK(); playlist_check_pos_current(); if (restart_playing) playlist_play(); else { mainwin_set_info_text(); playlistwin_update_list(); }}static void playlist_queue_toggle(void *data){ GList *temp; temp = g_list_find(queued_list, data); if (temp) { queued_list = g_list_remove_link(queued_list, temp); g_list_free_1(temp); } else queued_list = g_list_append(queued_list, data);}void playlist_queue_selected(void){ GList *node; PL_LOCK(); for (node = get_playlist(); node; node = node->next) { PlaylistEntry *entry = node->data; if (!entry->selected) continue; playlist_queue_toggle(entry); } PL_UNLOCK(); playlistwin_update_list();} void playlist_queue_position(int pos){ void *entry; PL_LOCK(); entry = g_list_nth_data(playlist, pos); playlist_queue_toggle(entry); PL_UNLOCK(); playlistwin_update_list();} gboolean playlist_is_position_queued(int pos){ PlaylistEntry *entry; GList *temp; PL_LOCK(); entry = g_list_nth_data(playlist, pos); temp = g_list_find(queued_list, entry); PL_UNLOCK(); return temp != NULL;} void playlist_clear_queue(void){ PL_LOCK(); g_list_free(queued_list); queued_list = NULL; PL_UNLOCK(); playlistwin_update_list();} int playlist_get_queue_position(PlaylistEntry *entry){ return g_list_index(queued_list, entry);}void playlist_set_position(int pos){ GList *node; gboolean restart_playing = FALSE; PL_LOCK(); if (!playlist) { PL_UNLOCK(); return; } node = g_list_nth(playlist, pos); if (!node) { PL_UNLOCK(); return; } if (get_input_playing()) { /* We need to stop before changing playlist_position */ PL_UNLOCK(); input_stop(); PL_LOCK(); restart_playing = TRUE; } playlist_position = node->data; PL_UNLOCK(); playlist_check_pos_current(); if (restart_playing) playlist_play(); else { mainwin_set_info_text(); playlistwin_update_list(); } /* * Regenerate the shuffle list when the user set a position * manually */ playlist_generate_shuffle_list();}void playlist_eof_reached(void){ GList *plist_pos_list; input_stop(); PL_LOCK(); plist_pos_list = find_playlist_position_list(); if (cfg.no_playlist_advance) { PL_UNLOCK(); mainwin_clear_song_info(); if (cfg.repeat) playlist_play(); return; } if (queued_list) play_queued(); else if (!g_list_next(plist_pos_list)) { if (cfg.shuffle) { playlist_position = NULL; __playlist_generate_shuffle_list(); } else playlist_position = playlist->data; if (!cfg.repeat) { PL_UNLOCK(); mainwin_clear_song_info(); mainwin_set_info_text(); return; } } else playlist_position = plist_pos_list->next->data; PL_UNLOCK(); playlist_check_pos_current(); playlist_play(); mainwin_set_info_text(); playlistwin_update_list();}int get_playlist_length(void){ int retval; PL_LOCK(); retval = __get_playlist_length(); PL_UNLOCK(); return retval;}static int __get_playlist_length(void){ /* Caller should hold playlist_mutex */ if (playlist) return(g_list_length(playlist)); return 0;}char *playlist_get_info_text(void){ char *text, *title, *tmp, *numbers, *length; PL_LOCK(); if (!playlist_position) { PL_UNLOCK(); return NULL; } if (playlist_position->title) title = playlist_position->title; else title = g_basename(playlist_position->filename); /* * If the user don't want numbers in the playlist, don't * display them in other parts of XMMS */ if (cfg.show_numbers_in_pl) numbers = g_strdup_printf("%d. ", __get_playlist_position() + 1); else numbers = g_strdup(""); if (playlist_position->length != -1) length = g_strdup_printf(" (%d:%-2.2d)", playlist_position->length / 60000, (playlist_position->length / 1000) % 60); else length = g_strdup(""); text = g_strdup_printf("%s%s%s", numbers, title, length); g_free(numbers); g_free(length); PL_UNLOCK(); if (cfg.convert_underscore) while ((tmp = strchr(text, '_')) != NULL) *tmp = ' '; if (cfg.convert_twenty) while ((tmp = strstr(text, "%20")) != NULL) { char *tmp2; tmp2 = tmp + 3; *(tmp++) = ' '; while (*tmp2) *(tmp++) = *(tmp2++); *tmp = '\0'; } return text;}int playlist_get_current_length(void){ int retval = 0; PL_LOCK(); if (playlist && playlist_position) retval = playlist_position->length; PL_UNLOCK(); return retval;}gboolean playlist_save(char *filename, gboolean is_pls){ GList *node; FILE *file; if ((file = fopen(filename, "w")) == NULL) return FALSE; if (is_pls) { is_pls = TRUE; fprintf(file, "[playlist]\n"); fprintf(file, "NumberOfEntries=%d\n", get_playlist_length()); } else if (cfg.use_pl_metadata) fprintf(file, "#EXTM3U\n"); PL_LOCK(); node = playlist; while (node) { PlaylistEntry *entry = node->data; if (is_pls) fprintf(file, "File%d=%s\n", g_list_position(playlist, node) + 1, entry->filename); else { if (entry->title && cfg.use_pl_metadata) { int seconds; if (entry->length > 0) seconds = (entry->length) / 1000; else seconds = -1; fprintf(file, "#EXTINF:%d,%s\n", seconds, entry->title); } fprintf(file, "%s\n", entry->filename); } node = g_list_next(node); } PL_UNLOCK(); return (fclose(file) == 0);}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){ char *temp, *path; filename = g_strstrip(filename); if (cfg.use_backslash_as_dir_delimiter) { while ((temp = strchr(filename, '\\')) != NULL) *temp = '/'; } if (filename[0] != '/' && !strstr(filename, "://")) { path = g_strdup(playlist_name); temp = strrchr(path, '/'); if (temp) *temp = '\0'; else { __playlist_ins_with_info(filename, pos, title, len); return; } temp = g_strdup_printf("%s/%s", path, filename); __playlist_ins_with_info(temp, pos, title, len); g_free(temp); g_free(path); } else __playlist_ins_with_info(filename, pos, title, len);}static void parse_extm3u_info(char *info, char **title, int *length){ char *str; *title = NULL; *length = -1; if (!info) return; g_return_if_fail(strlen(info) >= 8); *length = atoi(info + 8); if (*length <= 0) *length = -1; else *length *= 1000; if ((str = strchr(info, ',')) != NULL) { *title = g_strdup(str + 1); g_strstrip(*title); if (strlen(*title) < 1) { g_free(*title); *title = NULL; } }}static guint playlist_load_ins(char * filename, long pos){ FILE *file; char *line, *ext; guint entries = 0; int linelen = 1024; gboolean extm3u = FALSE; char *ext_info = NULL, *ext_title = NULL; int ext_len = -1; ext = strrchr(filename, '.'); if (ext && !strcasecmp(ext, ".pls")) { int noe, i; char key[10]; line = read_ini_string(filename, "playlist", "NumberOfEntries"); if (line == NULL) return 0; noe = atoi(line); g_free(line); for (i = 1; i <= noe; i++) { g_snprintf(key, 10, "File%d", i); line = read_ini_string_no_comment(filename, "playlist", key); if (line != NULL) { playlist_load_ins_file(line, filename, pos, NULL, -1); entries++; if (pos >= 0) pos++; g_free(line); } } playlist_generate_shuffle_list(); playlistwin_update_list(); return entries; } /* * Seems like an m3u. Maybe we should do some sanity checking * here? If someone accidentally selects something else, we * will try to read it. */ if ((file = fopen(filename, "r")) == NULL) return 0; line = g_malloc(linelen); while (fgets(line, linelen, file)) { while (strlen(line) == linelen - 1 && line[strlen(line) - 1] != '\n') { linelen += 1024; line = g_realloc(line, linelen); fgets(&line[strlen(line)], 1024, file); } while (line[strlen(line) - 1] == '\r' || line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; if (!strncmp(line, "#EXTM3U", 8)) { extm3u = TRUE; continue; } if (extm3u && !strncmp(line, "#EXTINF:", 8)) { if (ext_info) g_free(ext_info); ext_info = g_strdup(line); continue; } if (line[0] == '#') { if (ext_info) { g_free(ext_info); ext_info = NULL; } continue; } if (extm3u) { if (cfg.use_pl_metadata) parse_extm3u_info(ext_info, &ext_title, &ext_len); g_free(ext_info); ext_info = NULL; } playlist_load_ins_file(line, filename, pos, ext_title, ext_len); g_free(ext_title); ext_title = NULL; ext_len = -1; entries++; if (pos >= 0) pos++; } fclose(file); g_free(line); playlist_generate_shuffle_list(); playlistwin_update_list(); return entries;}GList *get_playlist(void){ /* Caller should hold playlist_mutex */ return playlist;}int __get_playlist_position(void){ /* Caller should hold playlist_mutex */ if (playlist && playlist_position) return g_list_index(playlist, playlist_position); return 0;}int get_playlist_position(void){ int retval; PL_LOCK(); retval = __get_playlist_position(); PL_UNLOCK(); return retval;}char * playlist_get_filename(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->filename); PL_UNLOCK(); return ret;}char * playlist_get_songtitle(int pos){ char *title = NULL, *filename; 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; filename = g_strdup(entry->filename); if (entry->title == NULL && entry->length == -1) { if (playlist_get_info_entry(entry)) title = g_strdup(entry->title); PL_UNLOCK(); } else { title = g_strdup(entry->title); PL_UNLOCK(); } if (title == NULL) title = g_strdup(g_basename(filename)); g_free(filename); return title;}int playlist_get_songtime(int pos){ int retval = -1; PlaylistEntry *entry; GList *node; PL_LOCK(); if (!playlist) { PL_UNLOCK(); return -1; } node = g_list_nth(playlist, pos); if (!node) { PL_UNLOCK(); return -1; } entry = node->data; if (entry->title == NULL && entry->length == -1) { if (playlist_get_info_entry(entry)) retval = entry->length; PL_UNLOCK(); } else { retval = entry->length; PL_UNLOCK(); } return retval;}static int playlist_sort_by_title_cmpfunc(PlaylistEntry * a, PlaylistEntry * b){ char *a_title, *b_title; if (a->title) a_title = a->title; else { if (strrchr(a->filename, '/')) a_title = strrchr(a->filename, '/') + 1; else a_title = a->filename; } if (b->title) b_title = b->title; else { if (strrchr(a->filename, '/')) b_title = strrchr(b->filename, '/') + 1; else b_title = b->filename; } return strcasecmp(a_title, b_title);}void playlist_sort_by_title(void){ PL_LOCK(); playlist = g_list_sort(playlist, (GCompareFunc) playlist_sort_by_title_cmpfunc); PL_UNLOCK();}static int playlist_sort_by_filename_cmpfunc(PlaylistEntry * a, PlaylistEntry * b){ char *a_filename, *b_filename; if (strrchr(a->filename, '/'))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -