static int treeplaylist_callback(int action, const struct menu_item_ex *this_item) { switch (action) { case ACTION_REQUEST_MENUITEM: if (this_item == &tree_playlist_menu) { if (((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) || ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U)|| (selected_file_attr & ATTR_DIRECTORY)) { return action; } } else if (this_item == &view_playlist_item) { if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U && context == CONTEXT_TREE) { return action; } } else if (this_item == &i_shuf_pl_item) { if ((audio_status() & AUDIO_STATUS_PLAY) || (selected_file_attr & ATTR_DIRECTORY) || ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U)) { return action; } } else if (this_item == &i_last_shuf_pl_item || this_item == &q_last_shuf_pl_item) { if ((playlist_amount() > 0) && (audio_status() & AUDIO_STATUS_PLAY) && ((selected_file_attr & ATTR_DIRECTORY) || ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U))) { return action; } } return ACTION_EXIT_MENUITEM; break; } return action; }
static void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps, struct skin_viewport* skin_viewport, unsigned long refresh_type) { struct screen *display = gwps->display; char linebuf[MAX_LINE]; skin_render_func func = skin_render_line; struct skin_element* line = viewport; struct skin_draw_info info = { .gwps = gwps, .buf = linebuf, .buf_size = sizeof(linebuf), .line_number = 0, .no_line_break = false, .line_scrolls = false, .refresh_type = refresh_type, .skin_vp = skin_viewport, .offset = 0 }; struct align_pos * align = &info.align; bool needs_update; #ifdef HAVE_LCD_BITMAP /* Set images to not to be displayed */ struct skin_token_list *imglist = gwps->data->images; while (imglist) { struct gui_img *img = (struct gui_img *)imglist->token->value.data; img->display = -1; imglist = imglist->next; } #endif while (line) { linebuf[0] = '\0'; info.no_line_break = false; info.line_scrolls = false; info.force_redraw = false; info.cur_align_start = info.buf; align->left = info.buf; align->center = NULL; align->right = NULL; if (line->type == LINE_ALTERNATOR) func = skin_render_alternator; else if (line->type == LINE) func = skin_render_line; needs_update = func(line, &info); #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) if (skin_viewport->vp.fg_pattern != skin_viewport->start_fgcolour || skin_viewport->vp.bg_pattern != skin_viewport->start_bgcolour) { /* 2bit lcd drivers need lcd_set_viewport() to be called to change * the colour, 16bit doesnt. But doing this makes static text * get the new colour also */ needs_update = true; display->set_viewport(&skin_viewport->vp); } #endif /* only update if the line needs to be, and there is something to write */ if (refresh_type && needs_update) { if (info.line_scrolls) { /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_type & SKIN_REFRESH_SCROLL) || info.force_redraw) write_line(display, align, info.line_number, true); } else write_line(display, align, info.line_number, false); } if (!info.no_line_break) info.line_number++; line = line->next; } #ifdef HAVE_LCD_BITMAP wps_display_images(gwps, &skin_viewport->vp); #endif } void skin_render(struct gui_wps *gwps, unsigned refresh_mode) { struct wps_data *data = gwps->data; struct screen *display = gwps->display; struct skin_element* viewport = data->tree; struct skin_viewport* skin_viewport; int old_refresh_mode = refresh_mode; #ifdef HAVE_LCD_CHARCELLS int i; for (i = 0; i < 8; i++) { if (data->wps_progress_pat[i] == 0) data->wps_progress_pat[i] = display->get_locked_pattern(); } #endif viewport = data->tree; skin_viewport = (struct skin_viewport *)viewport->data; if (skin_viewport->label && viewport->next && !strcmp(skin_viewport->label,VP_DEFAULT_LABEL)) refresh_mode = 0; for (viewport = data->tree; viewport; viewport = viewport->next) { /* SETUP */ skin_viewport = (struct skin_viewport*)viewport->data; unsigned vp_refresh_mode = refresh_mode; #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour; skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour; #endif /* dont redraw the viewport if its disabled */ if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE) { /* don't draw anything into this one */ vp_refresh_mode = 0; } else if ((skin_viewport->hidden_flags&VP_DRAW_HIDDEN)) { skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN; continue; } else if (((skin_viewport->hidden_flags& (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)) == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))) { vp_refresh_mode = SKIN_REFRESH_ALL; skin_viewport->hidden_flags = VP_DRAW_HIDEABLE; } display->set_viewport(&skin_viewport->vp); if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL) { display->clear_viewport(); } /* render */ if (viewport->children_count) skin_render_viewport(viewport->children[0], gwps, skin_viewport, vp_refresh_mode); refresh_mode = old_refresh_mode; } /* Restore the default viewport */ display->set_viewport(NULL); display->update(); } #ifdef HAVE_LCD_BITMAP static __attribute__((noinline)) void skin_render_playlistviewer(struct playlistviewer* viewer, struct gui_wps *gwps, struct skin_viewport* skin_viewport, unsigned long refresh_type) { struct screen *display = gwps->display; char linebuf[MAX_LINE]; skin_render_func func = skin_render_line; struct skin_element* line; struct skin_draw_info info = { .gwps = gwps, .buf = linebuf, .buf_size = sizeof(linebuf), .line_number = 0, .no_line_break = false, .line_scrolls = false, .refresh_type = refresh_type, .skin_vp = skin_viewport, .offset = viewer->start_offset }; struct align_pos * align = &info.align; bool needs_update; int cur_pos, start_item, max; int nb_lines = viewport_get_nb_lines(viewer->vp); #if CONFIG_TUNER if (current_screen() == GO_TO_FM) { cur_pos = radio_current_preset(); start_item = cur_pos + viewer->start_offset; max = start_item+radio_preset_count(); } else #endif { struct cuesheet *cue = skin_get_global_state()->id3 ? skin_get_global_state()->id3->cuesheet : NULL; cur_pos = playlist_get_display_index(); max = playlist_amount()+1; if (cue) max += cue->track_count; start_item = MAX(0, cur_pos + viewer->start_offset); } if (max-start_item > nb_lines) max = start_item + nb_lines; line = viewer->line; while (start_item < max) { linebuf[0] = '\0'; info.no_line_break = false; info.line_scrolls = false; info.force_redraw = false; info.cur_align_start = info.buf; align->left = info.buf; align->center = NULL; align->right = NULL; if (line->type == LINE_ALTERNATOR) func = skin_render_alternator; else if (line->type == LINE) func = skin_render_line; needs_update = func(line, &info); /* only update if the line needs to be, and there is something to write */ if (refresh_type && needs_update) { if (info.line_scrolls) { /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_type & SKIN_REFRESH_SCROLL) || info.force_redraw) write_line(display, align, info.line_number, true); } else write_line(display, align, info.line_number, false); } info.line_number++; info.offset++; start_item++; } }
bool bookmark_play(char *resume_file, int index, int offset, int seed, char *filename) { int i; char* suffix = strrchr(resume_file, '.'); bool started = false; if (suffix != NULL && (!strcasecmp(suffix, ".m3u") || !strcasecmp(suffix, ".m3u8"))) { /* Playlist playback */ char* slash; /* check that the file exists */ if(!file_exists(resume_file)) return false; slash = strrchr(resume_file,'/'); if (slash) { char* cp; *slash=0; cp=resume_file; if (!cp[0]) cp="/"; if (playlist_create(cp, slash+1) != -1) { if (global_settings.playlist_shuffle) playlist_shuffle(seed, -1); playlist_start(index,offset); started = true; } *slash='/'; } } else { /* Directory playback */ lastdir[0]='\0'; if (playlist_create(resume_file, NULL) != -1) { char filename_buf[MAX_PATH + 1]; const char* peek_filename; resume_directory(resume_file); if (global_settings.playlist_shuffle) playlist_shuffle(seed, -1); /* Check if the file is at the same spot in the directory, else search for it */ peek_filename = playlist_peek(index, filename_buf, sizeof(filename_buf)); if (peek_filename == NULL) { /* playlist has shrunk, search from the top */ index = 0; peek_filename = playlist_peek(index, filename_buf, sizeof(filename_buf)); if (peek_filename == NULL) return false; } if (strcmp(strrchr(peek_filename, '/') + 1, filename)) { for ( i=0; i < playlist_amount(); i++ ) { peek_filename = playlist_peek(i, filename_buf, sizeof(filename_buf)); if (peek_filename == NULL) return false; if (!strcmp(strrchr(peek_filename, '/') + 1, filename)) break; } if (i < playlist_amount()) index = i; else return false; } playlist_start(index,offset); started = true; } } if (started) start_wps = true; return started; }
/* CONTEXT_[TREE|ID3DB] playlist options */ static bool add_to_playlist(int position, bool queue) { bool new_playlist = !(audio_status() & AUDIO_STATUS_PLAY); const char *lines[] = { ID2P(LANG_RECURSE_DIRECTORY_QUESTION), selected_file }; const struct text_message message={lines, 2}; splash(0, ID2P(LANG_WAIT)); if (new_playlist) playlist_create(NULL, NULL); /* always set seed before inserting shuffled */ if (position == PLAYLIST_INSERT_SHUFFLED || position == PLAYLIST_INSERT_LAST_SHUFFLED) { srand(current_tick); if (position == PLAYLIST_INSERT_LAST_SHUFFLED) playlist_set_last_shuffled_start(); } #ifdef HAVE_TAGCACHE if (context == CONTEXT_ID3DB) { tagtree_insert_selection_playlist(position, queue); } else #endif { if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) playlist_insert_track(NULL, selected_file, position, queue, true); else if (selected_file_attr & ATTR_DIRECTORY) { bool recurse = false; if (global_settings.recursive_dir_insert != RECURSE_ASK) recurse = (bool)global_settings.recursive_dir_insert; else { /* Ask if user wants to recurse directory */ recurse = (gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES); } playlist_insert_directory(NULL, selected_file, position, queue, recurse); } else if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U) playlist_insert_playlist(NULL, selected_file, position, queue); } if (new_playlist && (playlist_amount() > 0)) { /* nothing is currently playing so begin playing what we just inserted */ if (global_settings.playlist_shuffle) playlist_shuffle(current_tick, -1); playlist_start(0,0); onplay_result = ONPLAY_START_PLAY; } return false; }
/* Initialize the playlist viewer. */ static bool playlist_viewer_init(struct playlist_viewer * viewer, const char* filename, bool reload) { char* buffer; size_t buffer_size; bool is_playing = audio_status() & (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE); bool have_list = filename || is_playing; if (!have_list && (global_status.resume_index != -1)) { /* Try to restore the list from control file */ have_list = (playlist_resume() != -1); } if (!have_list && (playlist_amount() > 0)) { /*If dynamic playlist still exists, view it anyway even if playback has reached the end of the playlist */ have_list = true; } if (!have_list) { /* Nothing to view, exit */ splash(HZ, str(LANG_CATALOG_NO_PLAYLISTS)); return false; } buffer = plugin_get_buffer(&buffer_size); if (!buffer) return false; if (!filename) viewer->playlist = NULL; else { /* Viewing playlist on disk */ const char *dir, *file; char *temp_ptr; char *index_buffer = NULL; ssize_t index_buffer_size = 0; viewer->playlist = &temp_playlist; /* Separate directory from filename */ temp_ptr = strrchr(filename+1,'/'); if (temp_ptr) { *temp_ptr = 0; dir = filename; file = temp_ptr + 1; } else { dir = "/"; file = filename+1; } if (is_playing) { /* Something is playing, use half the plugin buffer for playlist indices */ index_buffer_size = buffer_size / 2; index_buffer = buffer; } playlist_create_ex(viewer->playlist, dir, file, index_buffer, index_buffer_size, buffer+index_buffer_size, buffer_size-index_buffer_size); if (temp_ptr) *temp_ptr = '/'; buffer += index_buffer_size; buffer_size -= index_buffer_size; } playlist_buffer_init(&viewer->buffer, buffer, buffer_size); viewer->moving_track = -1; viewer->moving_playlist_index = -1; if (!reload) { if (viewer->playlist) viewer->selected_track = 0; else viewer->selected_track = playlist_get_display_index() - 1; } if (!update_playlist(true)) return false; return true; }