make undo_save_state a task

This commit is contained in:
Brad Parker 2016-10-02 16:04:09 -04:00
parent 18290ae777
commit cf3ae942c2
4 changed files with 121 additions and 69 deletions

View File

@ -1624,14 +1624,7 @@ static void command_event_undo_save_state(char *s, size_t len)
}
if (!content_undo_save_state())
{
snprintf(s, len, "%s \"%s\".",
msg_hash_to_str(MSG_FAILED_TO_UNDO_SAVE_STATE),
"RAM");
return;
}
strlcpy(s, msg_hash_to_str(MSG_RESTORED_OLD_SAVE_STATE), len);
}
/**

View File

@ -141,7 +141,7 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
"Complete by toggling eject again.");
break;
case RARCH_GRAB_MOUSE_TOGGLE:
snprintf(s, len,
snprintf(s, len,
"Toggles mouse grab. \n"
" \n"
"When mouse is grabbed, RetroArch hides the \n"
@ -485,7 +485,7 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
"Hide input descriptors that were not set \n"
"by the core.");
break;
case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE:
case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE:
snprintf(s, len,
"Video refresh rate of your monitor. \n"
"Used to calculate a suitable audio input rate.");
@ -634,7 +634,7 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
char u[501];
char t[501];
strlcpy(t,
strlcpy(t,
"RetroArch relies on an unique form of\n"
"audio/video synchronization where it needs to be\n"
"calibrated against the refresh rate of your\n"
@ -1500,7 +1500,7 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
" Possible values are [0.0, 1.0].");
break;
case MENU_ENUM_LABEL_INPUT_TURBO_PERIOD:
snprintf(s, len,
snprintf(s, len,
"Turbo period.\n"
" \n"
"Describes the period of which turbo-enabled\n"
@ -1510,7 +1510,7 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
);
break;
case MENU_ENUM_LABEL_INPUT_DUTY_CYCLE:
snprintf(s, len,
snprintf(s, len,
"Duty cycle.\n"
" \n"
"Describes how long the period of a turbo-enabled\n"
@ -2602,7 +2602,7 @@ static const char *menu_hash_to_str_us_label_enum(enum msg_hash_enums msg)
return "video_aspect_ratio_auto";
case MENU_ENUM_LABEL_VIDEO_FORCE_ASPECT:
return "video_force_aspect";
case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE:
case MENU_ENUM_LABEL_VIDEO_REFRESH_RATE:
return "video_refresh_rate";
case MENU_ENUM_LABEL_VIDEO_FORCE_SRGB_DISABLE:
return "video_force_srgb_disable";
@ -3335,6 +3335,8 @@ const char *msg_hash_to_str_us(enum msg_hash_enums msg)
return "to";
case MSG_SAVING_RAM_TYPE:
return "Saving RAM type";
case MSG_UNDOING_SAVE_STATE:
return "Undoing save state";
case MSG_SAVING_STATE:
return "Saving state";
case MSG_LOADING_STATE:

View File

@ -1,7 +1,7 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2016 - Daniel De Matteis
*
*
* 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-
* ation, either version 3 of the License, or (at your option) any later version.
@ -251,6 +251,7 @@ enum msg_hash_enums
MSG_FAILED_TO_TAKE_SCREENSHOT,
MSG_CUSTOM_TIMING_GIVEN,
MSG_SAVING_STATE,
MSG_UNDOING_SAVE_STATE,
MSG_LOADING_STATE,
MSG_FAILED_TO_SAVE_STATE_TO,
MSG_FAILED_TO_SAVE_SRAM,
@ -399,7 +400,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_CPU_CORES,
/* Input */
MENU_ENUM_LABEL_INPUT_LIBRETRO_DEVICE,
MENU_ENUM_LABEL_INPUT_LIBRETRO_DEVICE_LAST = MENU_ENUM_LABEL_INPUT_LIBRETRO_DEVICE + MAX_USERS,
MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE,
@ -563,7 +564,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_VIDEO_VIEWPORT_CUSTOM_WIDTH,
MENU_ENUM_LABEL_VALUE_VIDEO_VIEWPORT_CUSTOM_HEIGHT,
MENU_ENUM_LABEL_VALUE_VIDEO_DISABLE_COMPOSITION,
MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE,
MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY,

View File

@ -83,6 +83,7 @@ typedef struct
ssize_t bytes_read;
bool load_to_backup_buffer;
bool autoload;
bool undo_save;
} save_task_state_t;
typedef save_task_state_t load_task_data_t;
@ -466,17 +467,9 @@ bool content_undo_load_state(void)
return ret;
}
/**
* undo_save_state:
* Reverts the last save operation
*
* Returns: true if successful, false otherwise.
**/
bool content_undo_save_state(void)
static void undo_save_state_cb(void *task_data,
void *user_data, const char *error)
{
bool ret = filestream_write_file(undo_save_buf.path,
undo_save_buf.data, undo_save_buf.size);
/* Wipe the save file buffer as it's intended to be one use only */
undo_save_buf.path[0] = '\0';
undo_save_buf.size = 0;
@ -485,15 +478,6 @@ bool content_undo_save_state(void)
free(undo_save_buf.data);
undo_save_buf.data = NULL;
}
if (!ret)
{
RARCH_ERR("%s \"%s\".\n",
msg_hash_to_str(MSG_FAILED_TO_UNDO_SAVE_STATE),
undo_save_buf.path);
}
return ret;
}
/**
@ -514,33 +498,12 @@ static void task_save_handler_finished(retro_task_t *task,
task->error = strdup("Task canceled");
if (state->data)
{
if (state->undo_save && state->data == undo_save_buf.data)
undo_save_buf.data = NULL;
free(state->data);
free(state);
}
/**
* task_load_handler_finished:
* @task : the task to finish
* @state : the state associated with this task
*
* Close the loaded state file and finish the task.
**/
static void task_load_handler_finished(retro_task_t *task,
save_task_state_t *state)
{
load_task_data_t *task_data = NULL;
task->finished = true;
filestream_close(state->file);
if (!task->error && task->cancelled)
task->error = strdup("Task canceled");
task_data = (load_task_data_t*)calloc(1, sizeof(*task_data));
memcpy(task_data, state, sizeof(*task_data));
task->task_data = task_data;
state->data = NULL;
}
free(state);
}
@ -575,7 +538,20 @@ static void task_save_handler(retro_task_t *task)
if (task->cancelled || written != remaining)
{
char err[PATH_MAX_LENGTH] = {0};
snprintf(err, sizeof(err), "%s %s", msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), state->path);
if (state->undo_save)
{
RARCH_ERR("%s \"%s\".\n",
msg_hash_to_str(MSG_FAILED_TO_UNDO_SAVE_STATE),
undo_save_buf.path);
snprintf(err, sizeof(err), "%s \"%s\".",
msg_hash_to_str(MSG_FAILED_TO_UNDO_SAVE_STATE),
"RAM");
}
else
snprintf(err, sizeof(err), "%s %s", msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), state->path);
task->error = strdup(err);
task_save_handler_finished(task, state);
return;
@ -586,26 +562,106 @@ static void task_save_handler(retro_task_t *task)
settings_t *settings = config_get_ptr();
char msg[1024] = {0};
task_save_handler_finished(task, state);
if (task->title)
free(task->title);
task->title = NULL;
if (settings->state_slot < 0)
snprintf(msg, sizeof(msg), "%s #-1 (auto).",
msg_hash_to_str(MSG_SAVED_STATE_TO_SLOT));
if (state->undo_save)
{
strlcpy(msg, msg_hash_to_str(MSG_RESTORED_OLD_SAVE_STATE),
sizeof(msg));
}
else
snprintf(msg, sizeof(msg), "%s #%d.", msg_hash_to_str(MSG_SAVED_STATE_TO_SLOT),
settings->state_slot);
{
if (settings->state_slot < 0)
snprintf(msg, sizeof(msg), "%s #-1 (auto).",
msg_hash_to_str(MSG_SAVED_STATE_TO_SLOT));
else
snprintf(msg, sizeof(msg), "%s #%d.", msg_hash_to_str(MSG_SAVED_STATE_TO_SLOT),
settings->state_slot);
}
runloop_msg_queue_push(msg, 2, 180, true);
task_save_handler_finished(task, state);
return;
}
}
/**
* task_push_undo_save_state:
* @path : file path of the save state
* @data : the save state data to write
* @size : the total size of the save state
*
* Create a new task to undo the last save of the content state.
**/
static void task_push_undo_save_state(const char *path, void *data, size_t size)
{
retro_task_t *task = (retro_task_t*)calloc(1, sizeof(*task));
save_task_state_t *state = (save_task_state_t*)calloc(1, sizeof(*state));
if (!task || !state)
{
if (data)
free(data);
return;
}
strlcpy(state->path, path, sizeof(state->path));
state->data = data;
state->size = size;
state->undo_save = true;
task->state = state;
task->handler = task_save_handler;
task->callback = undo_save_state_cb;
task->title = strdup(msg_hash_to_str(MSG_UNDOING_SAVE_STATE));
task_queue_ctl(TASK_QUEUE_CTL_PUSH, task);
}
/**
* undo_save_state:
* Reverts the last save operation
*
* Returns: true if successful, false otherwise.
**/
bool content_undo_save_state(void)
{
task_push_undo_save_state(undo_save_buf.path,
undo_save_buf.data,
undo_save_buf.size);
return true;
}
/**
* task_load_handler_finished:
* @task : the task to finish
* @state : the state associated with this task
*
* Close the loaded state file and finish the task.
**/
static void task_load_handler_finished(retro_task_t *task,
save_task_state_t *state)
{
load_task_data_t *task_data = NULL;
task->finished = true;
filestream_close(state->file);
if (!task->error && task->cancelled)
task->error = strdup("Task canceled");
task_data = (load_task_data_t*)calloc(1, sizeof(*task_data));
memcpy(task_data, state, sizeof(*task_data));
task->task_data = task_data;
free(state);
}
/**
* task_load_handler:
* @task : the task being worked on