📄 playlist.c
字号:
case resume_shuffle: { /* str1=seed str2=first_index */ int seed; if (!str1 || !str2) { result = -1; exit_loop = true; break; } if (!sorted) { /* Always sort list before shuffling */ sort_playlist(playlist, false, false); } seed = atoi(str1); playlist->first_index = atoi(str2); if (randomise_playlist(playlist, seed, false, false) < 0) return -1; sorted = false; break; } case resume_unshuffle: { /* str1=first_index */ if (!str1) { result = -1; exit_loop = true; break; } playlist->first_index = atoi(str1); if (sort_playlist(playlist, false, false) < 0) return -1; sorted = true; break; } case resume_reset: { playlist->last_insert_pos = -1; break; } case resume_comment: default: break; } newline = true; /* to ignore any extra newlines */ current_command = resume_comment; } else if(newline) { newline = false; /* first non-comment line must always specify playlist */ if (first && *p != 'P' && *p != '#') { result = -1; exit_loop = true; break; } switch (*p) { case 'P': /* playlist can only be specified once */ if (!first) { result = -1; exit_loop = true; break; } current_command = resume_playlist; break; case 'A': current_command = resume_add; break; case 'Q': current_command = resume_queue; break; case 'D': current_command = resume_delete; break; case 'S': current_command = resume_shuffle; break; case 'U': current_command = resume_unshuffle; break; case 'R': current_command = resume_reset; break; case '#': current_command = resume_comment; break; default: result = -1; exit_loop = true; break; } str_count = -1; str1 = NULL; str2 = NULL; str3 = NULL; } else if(current_command != resume_comment) { /* all control file strings are separated with a colon. Replace the colon with 0 to get proper strings that can be used by commands above */ if (*p == ':') { *p = '\0'; str_count++; if ((count+1) < nread) { switch (str_count) { case 0: str1 = p+1; break; case 1: str2 = p+1; break; case 2: str3 = p+1; break; default: /* allow last string to contain colons */ *p = ':'; break; } } } } } if (result < 0) { splash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_INVALID)); return result; } if (!newline || (exit_loop && count<nread)) { /* We didn't end on a newline or we exited loop prematurely. Either way, re-read the remainder. NOTE: because of this, control file must always end with a newline */ count = last_newline; lseek(playlist->control_fd, total_read+count, SEEK_SET); } total_read += count; if (first) /* still looking for header */ nread = read(playlist->control_fd, buffer, PLAYLIST_COMMAND_SIZE<buflen?PLAYLIST_COMMAND_SIZE:buflen); else nread = read(playlist->control_fd, buffer, buflen); /* Terminate on EOF */ if(nread <= 0) { if (global_settings.resume_seed >= 0) { /* Apply shuffle command saved in settings */ if (global_settings.resume_seed == 0) sort_playlist(playlist, false, true); else { if (!sorted) sort_playlist(playlist, false, false); randomise_playlist(playlist, global_settings.resume_seed, false, true); } playlist->first_index = global_settings.resume_first_index; } break; } } return 0;}/* * Add track to in_ram playlist. Used when playing directories. */int playlist_add(char *filename){ struct playlist_info* playlist = ¤t_playlist; int len = strlen(filename); if((len+1 > playlist->buffer_size - playlist->buffer_end_pos) || (playlist->amount >= playlist->max_playlist_size)) { display_buffer_full(); return -1; } playlist->indices[playlist->amount++] = playlist->buffer_end_pos; strcpy(&playlist->buffer[playlist->buffer_end_pos], filename); playlist->buffer_end_pos += len; playlist->buffer[playlist->buffer_end_pos++] = '\0'; return 0;}/* shuffle newly created playlist using random seed. */int playlist_shuffle(int random_seed, int start_index){ struct playlist_info* playlist = ¤t_playlist; unsigned int seek_pos = 0; bool start_current = false; if (start_index >= 0 && global_settings.play_selected) { /* store the seek position before the shuffle */ seek_pos = playlist->indices[start_index]; playlist->index = global_settings.resume_first_index = playlist->first_index = start_index; start_current = true; } splash(0, true, str(LANG_PLAYLIST_SHUFFLE)); randomise_playlist(playlist, random_seed, start_current, true); /* Flush shuffle command to disk */ flush_pending_control(playlist); return playlist->index;}/* start playing current playlist at specified index/offset */int playlist_start(int start_index, int offset){ struct playlist_info* playlist = ¤t_playlist; playlist->index = start_index; mpeg_play(offset); return 0;}/* Returns false if 'steps' is out of bounds, else true */bool playlist_check(int steps){ struct playlist_info* playlist = ¤t_playlist; int index = get_next_index(playlist, steps); return (index >= 0);}/* get trackname of track that is "steps" away from current playing track. NULL is used to identify end of playlist */char* playlist_peek(int steps){ struct playlist_info* playlist = ¤t_playlist; int seek; int fd; char *temp_ptr; int index; bool control_file; index = get_next_index(playlist, steps); if (index < 0) return NULL; control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; if (get_filename(playlist, seek, control_file, now_playing, MAX_PATH+1) < 0) return NULL; temp_ptr = now_playing; if (!playlist->in_ram || control_file) { /* remove bogus dirs from beginning of path (workaround for buggy playlist creation tools) */ while (temp_ptr) { fd = open(temp_ptr, O_RDONLY); if (fd >= 0) { close(fd); break; } temp_ptr = strchr(temp_ptr+1, '/'); } if (!temp_ptr) { /* Even though this is an invalid file, we still need to pass a file name to the caller because NULL is used to indicate end of playlist */ return now_playing; } } return temp_ptr;}/* * Update indices as track has changed */int playlist_next(int steps){ struct playlist_info* playlist = ¤t_playlist; int index; if (steps > 0 && global_settings.repeat_mode != REPEAT_ONE) { int i, j; /* We need to delete all the queued songs */ for (i=0, j=steps; i<j; i++) { index = get_next_index(playlist, i); if (playlist->indices[index] & PLAYLIST_QUEUE_MASK) { remove_track_from_playlist(playlist, index, true); steps--; /* one less track */ } } } index = get_next_index(playlist, steps); playlist->index = index; if (playlist->last_insert_pos >= 0 && steps > 0) { /* check to see if we've gone beyond the last inserted track */ int cur = rotate_index(playlist, index); int last_pos = rotate_index(playlist, playlist->last_insert_pos); if (cur > last_pos) { /* reset last inserted track */ playlist->last_insert_pos = -1; if (playlist->control_fd >= 0) { int result = -1; mutex_lock(&playlist->control_mutex); if (lseek(playlist->control_fd, 0, SEEK_END) >= 0) { if (fprintf(playlist->control_fd, "R\n") > 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 index;}/* Get resume info for current playing song. If return value is -1 then settings shouldn't be saved. */int playlist_get_resume_info(int *resume_index){ struct playlist_info* playlist = ¤t_playlist; *resume_index = playlist->index; return 0;}/* Returns index of current playing track for display purposes. This value should not be used for resume purposes as it doesn't represent the actual index into the playlist */int playlist_get_display_index(void){ struct playlist_info* playlist = ¤t_playlist; /* first_index should always be index 0 for display purposes */ int index = rotate_index(playlist, playlist->index); return (index+1);}/* returns number of tracks in current playlist */int playlist_amount(void){ return playlist_amount_ex(NULL);}/* * Create a new playlist If playlist is not NULL then we're loading a * playlist off disk for viewing/editing. The index_buffer is used to store * playlist indices (required for and only used if !current playlist). The * temp_buffer (if not NULL) is used as a scratchpad when loading indices. */int playlist_create_ex(struct playlist_info* playlist, char* dir, char* file, void* index_buffer, int index_buffer_size, void* temp_buffer, int temp_buffer_size){ if (!playlist) playlist = ¤t_playlist; else { /* Initialize playlist structure */ int r = rand() % 10; playlist->current = false; /* Use random name for control file */ snprintf(playlist->control_filename, sizeof(playlist->control_filename), "%s.%d", PLAYLIST_CONTROL_FILE, r);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -