mirror of
https://gitlab.com/Mr_Goldberg/goldberg_emulator
synced 2025-05-23 21:57:40 +08:00
Redo image handling in settings.
Lock the buffers when modifying them. Notify when callers change a set avatar image. Create a get function for images. Allow deletion of previously loaded images, and reuse of their ids.
This commit is contained in:
parent
c593c3f8b8
commit
25d34a65c4
224
dll/settings.cpp
224
dll/settings.cpp
@ -16,7 +16,7 @@
|
|||||||
<http://www.gnu.org/licenses/>. */
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "dll.h"
|
||||||
|
|
||||||
std::string Settings::sanitize(std::string name)
|
std::string Settings::sanitize(std::string name)
|
||||||
{
|
{
|
||||||
@ -54,6 +54,28 @@ Settings::Settings(CSteamID steam_id, CGameID game_id, std::string name, std::st
|
|||||||
|
|
||||||
this->offline = offline;
|
this->offline = offline;
|
||||||
this->create_unknown_leaderboards = true;
|
this->create_unknown_leaderboards = true;
|
||||||
|
|
||||||
|
this->next_free = 1;
|
||||||
|
this->preferred_network_image_type = Image::JPG;
|
||||||
|
|
||||||
|
this->background_thread_exit = false;
|
||||||
|
PRINT_DEBUG("%s.\n", "Settings::Settings Creating new background_monitor thread");
|
||||||
|
background_monitor_thread = std::thread(Settings::background_monitor_entry, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::~Settings()
|
||||||
|
{
|
||||||
|
bool wait = false;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(background_thread_mutex);
|
||||||
|
if (background_monitor_thread.joinable()) {
|
||||||
|
background_thread_exit = true;
|
||||||
|
wait = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wait) {
|
||||||
|
background_monitor_thread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSteamID Settings::get_local_steam_id()
|
CSteamID Settings::get_local_steam_id()
|
||||||
@ -214,19 +236,126 @@ void Settings::setLeaderboard(std::string leaderboard, enum ELeaderboardSortMeth
|
|||||||
leaderboards[leaderboard] = leader;
|
leaderboards[leaderboard] = leader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Settings::find_next_free_image_ref() {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(images_mutex);
|
||||||
|
|
||||||
|
if (images.size() == 0) {
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
for (auto x : images) {
|
||||||
|
auto y = images.upper_bound(x.first);
|
||||||
|
if (y == images.end()) {
|
||||||
|
if ((x.first + 1) == 0) {
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ret = x.first + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((x.first + 1) < y->first) {
|
||||||
|
if ((x.first + 1) != 0) {
|
||||||
|
ret = x.first + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_free = ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Settings::remove_image(int ref) {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(images_mutex);
|
||||||
|
|
||||||
|
auto x = images.find(ref);
|
||||||
|
if (x != images.end()) {
|
||||||
|
images.erase(x);
|
||||||
|
ret = find_next_free_image_ref();
|
||||||
|
} else {
|
||||||
|
ret = next_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Settings::replace_image(int ref, std::string data, uint32 width, uint32 height)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(images_mutex);
|
||||||
|
int ret = 0;
|
||||||
|
if (ref == 0) {
|
||||||
|
ret = add_image(data, width, height);
|
||||||
|
} else {
|
||||||
|
auto t = images.find(ref);
|
||||||
|
if (t != images.end()) {
|
||||||
|
ret = t->first;
|
||||||
|
t->second.data = data;
|
||||||
|
t->second.width = width;
|
||||||
|
t->second.height = height;
|
||||||
|
} else {
|
||||||
|
ret = add_image(data, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int Settings::add_image(std::string data, uint32 width, uint32 height)
|
int Settings::add_image(std::string data, uint32 width, uint32 height)
|
||||||
{
|
{
|
||||||
int last = images.size() + 1;
|
int last = 0;
|
||||||
struct Image_Data dt;
|
std::lock_guard<std::recursive_mutex> lock(images_mutex);
|
||||||
dt.width = width;
|
if (next_free != 0) {
|
||||||
dt.height = height;
|
last = next_free;
|
||||||
dt.data = data;
|
struct Image_Data dt;
|
||||||
images[last] = dt;
|
dt.width = width;
|
||||||
|
dt.height = height;
|
||||||
|
dt.data = data;
|
||||||
|
images[last] = dt;
|
||||||
|
find_next_free_image_ref();
|
||||||
|
} else {
|
||||||
|
PRINT_DEBUG("%s.\n",
|
||||||
|
"Settings::add_image failed. Buffer is full");
|
||||||
|
}
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Settings::get_image(int ref, std::string * data, uint32 * width, uint32 * height)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(images_mutex);
|
||||||
|
int ret = 0;
|
||||||
|
auto t = images.find(ref);
|
||||||
|
if (t != images.end()) {
|
||||||
|
ret = t->first;
|
||||||
|
if (data != NULL) {
|
||||||
|
*data = t->second.data;
|
||||||
|
}
|
||||||
|
if (width != NULL) {
|
||||||
|
*width = t->second.width;
|
||||||
|
}
|
||||||
|
if (height != NULL) {
|
||||||
|
*height = t->second.height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
if (width != NULL) {
|
||||||
|
*width = 0;
|
||||||
|
}
|
||||||
|
if (height != NULL) {
|
||||||
|
*height = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int Settings::get_profile_image(int eAvatarSize)
|
int Settings::get_profile_image(int eAvatarSize)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(images_mutex);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (auto i : profile_images) {
|
for (auto i : profile_images) {
|
||||||
if (i.first == eAvatarSize) {
|
if (i.first == eAvatarSize) {
|
||||||
@ -237,6 +366,64 @@ int Settings::get_profile_image(int eAvatarSize)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Settings::background_monitor_entry(Settings * settings) {
|
||||||
|
PRINT_DEBUG("%s.\n", "Settings::background_monitor_entry thread starting");
|
||||||
|
if (settings != NULL) {
|
||||||
|
settings->background_monitor();
|
||||||
|
}
|
||||||
|
PRINT_DEBUG("%s.\n", "Settings::background_monitor_entry thread exiting");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::background_monitor() {
|
||||||
|
bool exit = false;
|
||||||
|
do {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(background_thread_mutex);
|
||||||
|
exit = background_thread_exit;
|
||||||
|
if (!exit) {
|
||||||
|
if (background_tasks.size() > 0) {
|
||||||
|
for (auto x = background_tasks.begin(); x != background_tasks.end(); x++) {
|
||||||
|
bool task_done = false;
|
||||||
|
Steam_Client * client = try_get_steam_client();
|
||||||
|
if (client != NULL) {
|
||||||
|
switch (x->id) {
|
||||||
|
case Settings_Background_Task_IDs::NOTIFY_AVATAR_IMAGE:
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%s.\n", "Settings::background_monitor Got NOTIFY_AVATAR_IMAGE task");
|
||||||
|
|
||||||
|
if (client != NULL && client->steam_friends != NULL) {
|
||||||
|
client->steam_friends->GetFriendAvatar(this->steam_id, k_EAvatarSize32x32);
|
||||||
|
client->steam_friends->GetFriendAvatar(this->steam_id, k_EAvatarSize64x64);
|
||||||
|
client->steam_friends->GetFriendAvatar(this->steam_id, k_EAvatarSize184x184);
|
||||||
|
task_done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PRINT_DEBUG("%s %d.\n", "Settings::background_monitor Unknown task", x->id);
|
||||||
|
task_done = true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if (task_done) {
|
||||||
|
background_tasks.erase(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(!exit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::create_background_notify_task(Settings_Background_Task_IDs id, void *arg = NULL) {
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(background_thread_mutex);
|
||||||
|
background_tasks.push_back(Settings_Background_Task{id, arg});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int Settings::set_profile_image(int eAvatarSize, Image_Data * image)
|
int Settings::set_profile_image(int eAvatarSize, Image_Data * image)
|
||||||
{
|
{
|
||||||
bool size_ok = false;
|
bool size_ok = false;
|
||||||
@ -252,11 +439,13 @@ int Settings::set_profile_image(int eAvatarSize, Image_Data * image)
|
|||||||
|
|
||||||
if (size_ok == true && image->data.length() > 0) {
|
if (size_ok == true && image->data.length() > 0) {
|
||||||
ref = this->add_image(image->data, image->width, image->height);
|
ref = this->add_image(image->data, image->width, image->height);
|
||||||
PRINT_DEBUG("set_profile_image %d -> %d.\n", eAvatarSize, ref);
|
PRINT_DEBUG("Settings::set_profile_image %d -> %d.\n", eAvatarSize, ref);
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(images_mutex);
|
||||||
profile_images[eAvatarSize] = ref;
|
profile_images[eAvatarSize] = ref;
|
||||||
|
create_background_notify_task(Settings_Background_Task_IDs::NOTIFY_AVATAR_IMAGE, NULL);
|
||||||
} else {
|
} else {
|
||||||
PRINT_DEBUG("%s %d %dx%d %"PRI_ZU".\n",
|
PRINT_DEBUG("%s %d %dx%d %"PRI_ZU".\n",
|
||||||
"set_profile_image failed",
|
"Settings::set_profile_image failed",
|
||||||
eAvatarSize,
|
eAvatarSize,
|
||||||
image->width,
|
image->width,
|
||||||
image->height,
|
image->height,
|
||||||
@ -266,3 +455,20 @@ int Settings::set_profile_image(int eAvatarSize, Image_Data * image)
|
|||||||
|
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Settings::set_preferred_network_image_type(int new_type)
|
||||||
|
{
|
||||||
|
switch (new_type) {
|
||||||
|
case Image::RAW:
|
||||||
|
case Image::PNG:
|
||||||
|
case Image::JPG:
|
||||||
|
this->preferred_network_image_type = new_type;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PRINT_DEBUG("%s %d.\n",
|
||||||
|
"Settings::set_preferred_network_image_type failed. Requested type",
|
||||||
|
new_type);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@ -65,11 +65,25 @@ struct Controller_Settings {
|
|||||||
std::map<std::string, std::map<std::string, std::pair<std::set<std::string>, std::string>>> action_set_layers;
|
std::map<std::string, std::map<std::string, std::pair<std::set<std::string>, std::string>>> action_set_layers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Settings_Background_Task_IDs {
|
||||||
|
NOTIFY_AVATAR_IMAGE = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Settings_Background_Task {
|
||||||
|
enum Settings_Background_Task_IDs id;
|
||||||
|
void * arg;
|
||||||
|
};
|
||||||
|
|
||||||
class Settings {
|
class Settings {
|
||||||
CSteamID steam_id;
|
CSteamID steam_id;
|
||||||
CGameID game_id;
|
CGameID game_id;
|
||||||
std::string name, language;
|
std::string name, language;
|
||||||
CSteamID lobby_id;
|
CSteamID lobby_id;
|
||||||
|
uint32 preferred_network_image_type;
|
||||||
|
bool background_thread_exit;
|
||||||
|
std::vector<Settings_Background_Task> background_tasks;
|
||||||
|
std::thread background_monitor_thread;
|
||||||
|
std::recursive_mutex background_thread_mutex;
|
||||||
|
|
||||||
bool unlockAllDLCs;
|
bool unlockAllDLCs;
|
||||||
bool offline;
|
bool offline;
|
||||||
@ -83,6 +97,12 @@ class Settings {
|
|||||||
std::map<int, int> profile_images;
|
std::map<int, int> profile_images;
|
||||||
bool create_unknown_leaderboards;
|
bool create_unknown_leaderboards;
|
||||||
uint16 port;
|
uint16 port;
|
||||||
|
int next_free;
|
||||||
|
|
||||||
|
int find_next_free_image_ref();
|
||||||
|
void create_background_notify_task(Settings_Background_Task_IDs id, void *arg);
|
||||||
|
static void background_monitor_entry(Settings * settings);
|
||||||
|
void background_monitor();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef LOBBY_CONNECT
|
#ifdef LOBBY_CONNECT
|
||||||
@ -90,8 +110,10 @@ public:
|
|||||||
#else
|
#else
|
||||||
static const bool is_lobby_connect = false;
|
static const bool is_lobby_connect = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string sanitize(std::string name);
|
static std::string sanitize(std::string name);
|
||||||
Settings(CSteamID steam_id, CGameID game_id, std::string name, std::string language, bool offline);
|
Settings(CSteamID steam_id, CGameID game_id, std::string name, std::string language, bool offline);
|
||||||
|
~Settings();
|
||||||
CSteamID get_local_steam_id();
|
CSteamID get_local_steam_id();
|
||||||
CGameID get_local_game_id();
|
CGameID get_local_game_id();
|
||||||
const char *get_local_name();
|
const char *get_local_name();
|
||||||
@ -146,10 +168,16 @@ public:
|
|||||||
std::set<uint64> subscribed_groups;
|
std::set<uint64> subscribed_groups;
|
||||||
|
|
||||||
//images
|
//images
|
||||||
|
std::recursive_mutex images_mutex;
|
||||||
std::map<int, struct Image_Data> images;
|
std::map<int, struct Image_Data> images;
|
||||||
|
int remove_image(int ref);
|
||||||
|
int replace_image(int ref, std::string data, uint32 width, uint32 height);
|
||||||
int add_image(std::string data, uint32 width, uint32 height);
|
int add_image(std::string data, uint32 width, uint32 height);
|
||||||
|
int get_image(int ref, std::string * data, uint32 * width, uint32 * height);
|
||||||
int get_profile_image(int eAvatarSize);
|
int get_profile_image(int eAvatarSize);
|
||||||
int set_profile_image(int eAvatarSize, Image_Data * image);
|
int set_profile_image(int eAvatarSize, Image_Data * image);
|
||||||
|
int get_preferred_network_image_type() { return this->preferred_network_image_type; }
|
||||||
|
void set_preferred_network_image_type(int new_type);
|
||||||
|
|
||||||
//controller
|
//controller
|
||||||
struct Controller_Settings controller_settings;
|
struct Controller_Settings controller_settings;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user