Merge pull request #2947 from leiradel/master

http tasks can now be cancelled; on-demand thumbnail download working
This commit is contained in:
Twinaphex 2016-05-05 15:37:11 +02:00
commit e02a81a96a
5 changed files with 137 additions and 18 deletions

View File

@ -82,7 +82,12 @@ enum task_queue_ctl_state
TASK_QUEUE_CTL_UNSET_THREADED,
TASK_QUEUE_CTL_IS_THREADED
TASK_QUEUE_CTL_IS_THREADED,
/**
* Signals a task to end without waiting for
* it to complete. */
TASK_QUEUE_CTL_CANCEL,
};
typedef struct retro_task retro_task_t;
@ -148,6 +153,8 @@ void task_queue_push_progress(retro_task_t *task);
bool task_queue_ctl(enum task_queue_ctl_state state, void *data);
void task_queue_cancel_task(void *task);
RETRO_END_DECLS
#endif

View File

@ -39,6 +39,7 @@ typedef struct
struct retro_task_impl
{
void (*push_running)(retro_task_t *);
void (*cancel)(void *);
void (*reset)(void);
void (*wait)(void);
void (*gather)(void);
@ -167,6 +168,12 @@ static void retro_task_regular_push_running(retro_task_t *task)
task_queue_put(&tasks_running, task);
}
static void retro_task_regular_cancel(void *task)
{
retro_task_t *t = task;
t->cancelled = true;
}
static void retro_task_regular_gather(void)
{
retro_task_t *task = NULL;
@ -232,6 +239,7 @@ static bool retro_task_regular_find(retro_task_finder_t func, void *user_data)
static struct retro_task_impl impl_regular = {
retro_task_regular_push_running,
retro_task_regular_cancel,
retro_task_regular_reset,
retro_task_regular_wait,
retro_task_regular_gather,
@ -255,6 +263,24 @@ static void retro_task_threaded_push_running(retro_task_t *task)
slock_unlock(running_lock);
}
static void retro_task_threaded_cancel(void *task)
{
retro_task_t *t;
slock_lock(running_lock);
for (t = tasks_running.front; t; t = t->next)
{
if (t == task)
{
t->cancelled = true;
break;
}
}
slock_unlock(running_lock);
}
static void retro_task_threaded_gather(void)
{
retro_task_t *task = NULL;
@ -400,6 +426,7 @@ static void retro_task_threaded_deinit(void)
static struct retro_task_impl impl_threaded = {
retro_task_threaded_push_running,
retro_task_threaded_cancel,
retro_task_threaded_reset,
retro_task_threaded_wait,
retro_task_threaded_gather,
@ -485,6 +512,9 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data)
case TASK_QUEUE_CTL_WAIT:
impl_current->wait();
break;
case TASK_QUEUE_CTL_CANCEL:
impl_current->cancel(data);
break;
case TASK_QUEUE_CTL_NONE:
default:
break;
@ -492,3 +522,8 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data)
return true;
}
void task_queue_cancel_task(void *task)
{
task_queue_ctl(TASK_QUEUE_CTL_CANCEL, task);
}

View File

@ -1,6 +1,6 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2016 - Daniel De Matteis
* Copyright (C) 2014-2015 - Jean-André Santoni
* Copyright (C) 2014-2015 - Jean-André Santoni
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
@ -47,6 +47,7 @@
#include "../../system.h"
#include "../../tasks/tasks_internal.h"
#include <streams/file_stream.h>
#define XMB_RIBBON_ROWS 64
#define XMB_RIBBON_COLS 64
@ -149,6 +150,7 @@ typedef struct xmb_handle
uintptr_t thumbnail;
float thumbnail_width;
float thumbnail_height;
void *thumbnail_task;
char background_file_path[PATH_MAX_LENGTH];
char thumbnail_file_path[PATH_MAX_LENGTH];
@ -719,17 +721,91 @@ static void menu_display_handle_thumbnail_upload(void *task_data,
free(img);
}
typedef struct
{
xmb_handle_t *xmb;
char file_path[1];
}
download_t;
static void cb_thumbnail_download(void *task_data, void *user_data, const char *error)
{
download_t *ud = user_data;
char output_path[PATH_MAX_LENGTH];
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
if (!data || !data->data)
goto finished;
ud->xmb->thumbnail_task = NULL;
strncpy(output_path, ud->file_path, sizeof(output_path));
output_path[sizeof(output_path) - 1] = 0;
path_basedir(output_path);
if (!path_mkdir(output_path))
{
RARCH_ERR("Error creating folders for file %s\n", ud->file_path);
goto finished;
}
if (!filestream_write_file(ud->file_path, data->data, data->len))
{
RARCH_ERR("Error writing file %s\n", ud->file_path);
goto finished;
}
/* Only update the image on the menu if the user is still at the same entry */
if (!strcmp(ud->file_path, ud->xmb->thumbnail_file_path))
rarch_task_push_image_load(ud->file_path, "cb_menu_thumbnail",
menu_display_handle_thumbnail_upload, NULL);
finished:
free(ud);
}
static void xmb_update_thumbnail_image(void *data)
{
xmb_handle_t *xmb = (xmb_handle_t*)data;
download_t *ud;
char buf[PATH_MAX_LENGTH];
if (!xmb)
return;
RARCH_LOG ("FILE: %s\n", xmb->thumbnail_file_path);
if (path_file_exists(xmb->thumbnail_file_path))
rarch_task_push_image_load(xmb->thumbnail_file_path, "cb_menu_thumbnail",
menu_display_handle_thumbnail_upload, NULL);
else if (xmb->depth == 1)
xmb->thumbnail = 0;
else
{
ud = (download_t *)malloc(sizeof(*ud) + strlen(xmb->thumbnail_file_path));
if (!ud)
{
RARCH_ERR("Error allocating memory for the thumbnail download userdata\n");
return;
}
ud->xmb = xmb;
strcpy(ud->file_path, strdup(xmb->thumbnail_file_path));
snprintf(buf, sizeof(buf), "http://thumbnails.libretro.com/%s/%s/%s",
xmb->title_name, xmb_thumbnails_ident(),
path_basename(xmb->thumbnail_file_path));
RARCH_LOG ("URL: %s\n", buf);
if (xmb->thumbnail_task)
task_queue_cancel_task(xmb->thumbnail_task);
xmb->thumbnail_task = rarch_task_push_http_transfer(buf, "", cb_thumbnail_download, ud);
if (xmb->depth == 1)
xmb->thumbnail = 0;
}
}
static void xmb_selection_pointer_changed(
@ -779,13 +855,6 @@ static void xmb_selection_pointer_changed(
{
ia = XMB_ITEM_ACTIVE_ALPHA;
iz = XMB_ITEM_ACTIVE_ZOOM;
depth = xmb_list_get_size(xmb, MENU_LIST_PLAIN);
if (strcmp(xmb_thumbnails_ident(), "OFF") && depth == 1)
{
xmb_update_thumbnail_path(xmb, i);
xmb_update_thumbnail_image(xmb);
}
}
if (real_iy < -threshold)
@ -2468,6 +2537,7 @@ static void *xmb_init(void **userdata)
xmb->depth = 1;
xmb->old_depth = 1;
xmb->alpha = 0;
xmb->thumbnail_task = NULL;
menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
/* TODO/FIXME - we don't use framebuffer at all
@ -2759,6 +2829,13 @@ static void xmb_navigation_set(void *data, bool scroll)
{
xmb_handle_t *xmb = (xmb_handle_t*)data;
xmb_selection_pointer_changed(xmb, true);
size_t selection;
if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection))
return;
xmb_update_thumbnail_path(xmb, selection);
xmb_update_thumbnail_image(xmb);
}
static void xmb_navigation_alphabet(void *data, size_t *unused)

View File

@ -208,7 +208,7 @@ static bool rarch_task_http_finder(retro_task_t *task, void *user_data)
return string_is_equal(http->connection.url, (const char*)user_data);
}
bool rarch_task_push_http_transfer(const char *url, const char *type,
void *rarch_task_push_http_transfer(const char *url, const char *type,
retro_task_callback_t cb, void *user_data)
{
char tmp[PATH_MAX_LENGTH];
@ -218,7 +218,7 @@ bool rarch_task_push_http_transfer(const char *url, const char *type,
http_handle_t *http = NULL;
if (string_is_empty(url))
return false;
return NULL;
find_data.func = rarch_task_http_finder;
find_data.userdata = (void*)url;
@ -227,13 +227,13 @@ bool rarch_task_push_http_transfer(const char *url, const char *type,
if (task_queue_ctl(TASK_QUEUE_CTL_FIND, &find_data))
{
RARCH_LOG("[http] '%s'' is already being downloaded.\n", url);
return false;
return NULL;
}
conn = net_http_connection_new(url);
if (!conn)
return false;
return NULL;
http = (http_handle_t*)calloc(1, sizeof(*http));
@ -267,7 +267,7 @@ bool rarch_task_push_http_transfer(const char *url, const char *type,
task_queue_ctl(TASK_QUEUE_CTL_PUSH, t);
return true;
return t;
error:
if (conn)
@ -277,5 +277,5 @@ error:
if (http)
free(http);
return false;
return NULL;
}

View File

@ -34,7 +34,7 @@ typedef struct {
size_t len;
} http_transfer_data_t;
bool rarch_task_push_http_transfer(const char *url, const char *type,
void *rarch_task_push_http_transfer(const char *url, const char *type,
retro_task_callback_t cb, void *userdata);
#endif