📄 playlist.c
字号:
flags = PLAYLIST_INSERT_TYPE_APPEND; break; } if (queue) flags |= PLAYLIST_QUEUED; /* shift indices so that track can be added */ for (i=playlist->amount; i>insert_position; i--) playlist->indices[i] = playlist->indices[i-1]; /* update stored indices if needed */ if (playlist->amount > 0 && insert_position <= playlist->index) playlist->index++; if (playlist->amount > 0 && insert_position <= playlist->first_index && position != PLAYLIST_PREPEND) { playlist->first_index++; if (seek_pos < 0 && playlist->current) { global_settings.resume_first_index = playlist->first_index; settings_save(); } } if (insert_position < playlist->last_insert_pos || (insert_position == playlist->last_insert_pos && position < 0)) playlist->last_insert_pos++; if (seek_pos < 0 && playlist->control_fd >= 0) { int result = -1; if (flush_pending_control(playlist) < 0) return -1; mutex_lock(&playlist->control_mutex); if (lseek(playlist->control_fd, 0, SEEK_END) >= 0) { if (fprintf(playlist->control_fd, "%c:%d:%d:", (queue?'Q':'A'), position, playlist->last_insert_pos) > 0) { /* save the position in file where track name is written */ seek_pos = lseek(playlist->control_fd, 0, SEEK_CUR); if (fprintf(playlist->control_fd, "%s\n", filename) > 0) result = 0; } } mutex_unlock(&playlist->control_mutex); if (result < 0) { splash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); return result; } } playlist->indices[insert_position] = flags | seek_pos; playlist->amount++; playlist->num_inserted_tracks++; return insert_position;}/* * Insert directory into playlist. May be called recursively. */static int add_directory_to_playlist(struct playlist_info* playlist, char *dirname, int *position, bool queue, int *count, bool recurse){ char buf[MAX_PATH+1]; char *count_str; int result = 0; int num_files = 0; bool buffer_full = false; int i; int dirfilter = SHOW_ALL; struct entry *files; /* use the tree browser dircache to load files */ files = load_and_sort_directory(dirname, &dirfilter, &num_files, &buffer_full); if(!files) { splash(HZ*2, true, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); return 0; } /* we've overwritten the dircache so tree browser will need to be reloaded */ reload_directory(); if (queue) count_str = str(LANG_PLAYLIST_QUEUE_COUNT); else count_str = str(LANG_PLAYLIST_INSERT_COUNT); for (i=0; i<num_files; i++) { /* user abort */#if defined(HAVE_PLAYER_KEYPAD) || defined(HAVE_NEO_KEYPAD) if (button_get(false) == BUTTON_STOP)#else if (button_get(false) == BUTTON_OFF)#endif { result = -1; break; } if (files[i].attr & ATTR_DIRECTORY) { if (recurse) { /* recursively add directories */ snprintf(buf, sizeof(buf), "%s/%s", dirname, files[i].name); result = add_directory_to_playlist(playlist, buf, position, queue, count, recurse); if (result < 0) break; /* we now need to reload our current directory */ files = load_and_sort_directory(dirname, &dirfilter, &num_files, &buffer_full); if (!files) { result = -1; break; } } else continue; } else if ((files[i].attr & TREE_ATTR_MASK) == TREE_ATTR_MPA) { int insert_pos; snprintf(buf, sizeof(buf), "%s/%s", dirname, files[i].name); insert_pos = add_track_to_playlist(playlist, buf, *position, queue, -1); if (insert_pos < 0) { result = -1; break; } (*count)++; /* Make sure tracks are inserted in correct order if user requests INSERT_FIRST */ if (*position == PLAYLIST_INSERT_FIRST || *position >= 0) *position = insert_pos + 1; if ((*count%PLAYLIST_DISPLAY_COUNT) == 0) { display_playlist_count(*count, count_str); if (*count == PLAYLIST_DISPLAY_COUNT) mpeg_flush_and_reload_tracks(); } /* let the other threads work */ yield(); } } return result;}/* * remove track at specified position */static int remove_track_from_playlist(struct playlist_info* playlist, int position, bool write){ int i; bool inserted; if (playlist->amount <= 0) return -1; inserted = playlist->indices[position] & PLAYLIST_INSERT_TYPE_MASK; /* shift indices now that track has been removed */ for (i=position; i<playlist->amount; i++) playlist->indices[i] = playlist->indices[i+1]; playlist->amount--; if (inserted) playlist->num_inserted_tracks--; else playlist->deleted = true; /* update stored indices if needed */ if (position < playlist->index) playlist->index--; if (position < playlist->first_index) { playlist->first_index--; if (write) { global_settings.resume_first_index = playlist->first_index; settings_save(); } } if (position <= playlist->last_insert_pos) playlist->last_insert_pos--; if (write && playlist->control_fd >= 0) { int result = -1; if (flush_pending_control(playlist) < 0) return -1; mutex_lock(&playlist->control_mutex); if (lseek(playlist->control_fd, 0, SEEK_END) >= 0) { if (fprintf(playlist->control_fd, "D:%d\n", position) > 0) { fsync(playlist->control_fd); result = 0; } } mutex_unlock(&playlist->control_mutex); if (result < 0) { splash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); return result; } } return 0;}/* * randomly rearrange the array of indices for the playlist. If start_current * is true then update the index to the new index of the current playing track */static int randomise_playlist(struct playlist_info* playlist, unsigned int seed, bool start_current, bool write){ int count; int candidate; int store; unsigned int current = playlist->indices[playlist->index]; /* seed 0 is used to identify sorted playlist for resume purposes */ if (seed == 0) seed = 1; /* seed with the given seed */ srand(seed); /* randomise entire indices list */ for(count = playlist->amount - 1; count >= 0; count--) { /* the rand is from 0 to RAND_MAX, so adjust to our value range */ candidate = rand() % (count + 1); /* now swap the values at the 'count' and 'candidate' positions */ store = playlist->indices[candidate]; playlist->indices[candidate] = playlist->indices[count]; playlist->indices[count] = store; } if (start_current) find_and_set_playlist_index(playlist, current); /* indices have been moved so last insert position is no longer valid */ playlist->last_insert_pos = -1; playlist->seed = seed; if (playlist->num_inserted_tracks > 0 || playlist->deleted) playlist->shuffle_modified = true; if (write) { /* Don't write to disk immediately. Instead, save in settings and only flush if playlist is modified (insertion/deletion) */ playlist->shuffle_flush = true; global_settings.resume_seed = seed; settings_save(); } return 0;}/* * Sort the array of indices for the playlist. If start_current is true then * set the index to the new index of the current song. */static int sort_playlist(struct playlist_info* playlist, bool start_current, bool write){ unsigned int current = playlist->indices[playlist->index]; if (playlist->amount > 0) qsort(playlist->indices, playlist->amount, sizeof(playlist->indices[0]), compare); if (start_current) find_and_set_playlist_index(playlist, current); /* indices have been moved so last insert position is no longer valid */ playlist->last_insert_pos = -1; if (!playlist->num_inserted_tracks && !playlist->deleted) playlist->shuffle_modified = false; if (write && playlist->control_fd >= 0) { /* Don't write to disk immediately. Instead, save in settings and only flush if playlist is modified (insertion/deletion) */ playlist->shuffle_flush = true; global_settings.resume_seed = 0; settings_save(); } return 0;}/* * returns the index of the track that is "steps" away from current playing * track. */static int get_next_index(struct playlist_info* playlist, int steps){ int current_index = playlist->index; int next_index = -1; if (playlist->amount <= 0) return -1; switch (global_settings.repeat_mode) { case REPEAT_OFF: { current_index = rotate_index(playlist, current_index); next_index = current_index+steps; if ((next_index < 0) || (next_index >= playlist->amount)) next_index = -1; else next_index = (next_index+playlist->first_index) % playlist->amount; break; } case REPEAT_ONE: next_index = current_index; break; case REPEAT_ALL: default: { next_index = (current_index+steps) % playlist->amount; while (next_index < 0) next_index += playlist->amount; if (steps >= playlist->amount) { int i, index; index = next_index; next_index = -1; /* second time around so skip the queued files */ for (i=0; i<playlist->amount; i++) { if (playlist->indices[index] & PLAYLIST_QUEUE_MASK) index = (index+1) % playlist->amount; else { next_index = index; break; } } } break; } } return next_index;}/* * Search for the seek track and set appropriate indices. Used after shuffle * to make sure the current index is still pointing to correct track. */static void find_and_set_playlist_index(struct playlist_info* playlist, unsigned int seek){ int i; /* Set the index to the current song */ for (i=0; i<playlist->amount; i++) { if (playlist->indices[i] == seek) { playlist->index = playlist->first_index = i; if (playlist->current) { global_settings.resume_first_index = i; settings_save(); } break; } }}/* * used to sort track indices. Sort order is as follows: * 1. Prepended tracks (in prepend order) * 2. Playlist/directory tracks (in playlist order) * 3. Inserted/Appended tracks (in insert order) */static int compare(const void* p1, const void* p2){ unsigned int* e1 = (unsigned int*) p1; unsigned int* e2 = (unsigned int*) p2; unsigned int flags1 = *e1 & PLAYLIST_INSERT_TYPE_MASK; unsigned int flags2 = *e2 & PLAYLIST_INSERT_TYPE_MASK; if (flags1 == flags2)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -