Initial
This commit is contained in:
commit
8be51ea5b8
|
@ -0,0 +1,10 @@
|
|||
*.o
|
||||
replays
|
||||
dolphin-emu
|
||||
minilauncher4slippi
|
||||
*.core
|
||||
portable.txt
|
||||
traversal_server
|
||||
User
|
||||
Sys
|
||||
*.iso
|
|
@ -0,0 +1,9 @@
|
|||
CC=cc
|
||||
CFLAGS=`pkg-config --cflags efl ecore elementary`
|
||||
LDFLAGS=`pkg-config --libs efl ecore elementary`
|
||||
|
||||
minilauncher4slippi: main.o replay.o
|
||||
$(CC) -o minilauncher4slippi main.o replay.o $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm minilauncher4slippi *.o
|
|
@ -0,0 +1,198 @@
|
|||
#include <stdio.h>
|
||||
#define EFL_BETA_API_SUPPORT
|
||||
#include <Ecore.h>
|
||||
#include <Efl_Ui.h>
|
||||
#include <Elementary.h>
|
||||
#include "replay.h"
|
||||
|
||||
char* game_path = "SSBM.iso";
|
||||
char* dolphin_emu_file = "./dolphin-emu";
|
||||
|
||||
Evas_Object* mainer;
|
||||
Evas_Object* win;
|
||||
Evas_Object* _tab_curr;
|
||||
Evas_Object* tab_home;
|
||||
//extern Evas_Object* tab_replays;
|
||||
Evas_Object* tab_config;
|
||||
|
||||
void
|
||||
_tab_switch_cb(void *_data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
Evas_Object** data = _data;
|
||||
elm_obj_box_unpack_all(mainer);
|
||||
evas_object_hide(_tab_curr);
|
||||
_tab_curr = *data;
|
||||
|
||||
evas_object_size_hint_weight_set(_tab_curr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||
|
||||
//elm_obj_box_recalculate(mainer);
|
||||
evas_object_show(mainer);
|
||||
evas_object_show(_tab_curr);
|
||||
elm_obj_box_pack_end(mainer, _tab_curr);
|
||||
|
||||
//evas_object_move(_tab_curr, 100, 15);
|
||||
//evas_object_resize(_tab_curr, 100, 100);
|
||||
|
||||
//Evas_Object* test = elm_button_add(mainer);
|
||||
//elm_object_text_set(test, "Test button");
|
||||
//evas_object_show(test);
|
||||
//elm_obj_box_pack_end(mainer, test);
|
||||
}
|
||||
|
||||
void
|
||||
_launch_slippi_job_end_cb(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
//Re-enable button so we can start again
|
||||
elm_object_disabled_set(data, EINA_FALSE);
|
||||
}
|
||||
|
||||
// Need to fork in a thread or EFL spergs out
|
||||
void
|
||||
_launch_slippi_job_cb(void *data, Ecore_Thread *thread)
|
||||
{
|
||||
char const* argv[64] = {dolphin_emu_file, "-e", game_path, "-b", NULL};
|
||||
if (fork() == 0)
|
||||
{
|
||||
execvp(argv[0], argv);
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
// Delay thread to prevent from launching again (button is disabled)
|
||||
usleep(2000000);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_launch_slippi_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
elm_object_disabled_set(data, EINA_TRUE);
|
||||
ecore_thread_run(_launch_slippi_job_cb,
|
||||
_launch_slippi_job_end_cb,
|
||||
_launch_slippi_job_end_cb, data);
|
||||
}
|
||||
|
||||
static void
|
||||
_replays_tab_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
elm_object_item_disabled_set(*(Elm_Object_Item**)data, EINA_TRUE);
|
||||
ecore_thread_run(_launch_slippi_job_cb,
|
||||
_launch_slippi_job_end_cb,
|
||||
_launch_slippi_job_end_cb, data);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tabs_init()
|
||||
{
|
||||
tab_home = elm_button_add(win);
|
||||
elm_object_text_set(tab_home, "Test button");
|
||||
evas_object_size_hint_align_set(tab_home, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
|
||||
|
||||
// BEGIN tab_replays
|
||||
tab_replays_setup(mainer);
|
||||
// END tab_replays
|
||||
}
|
||||
|
||||
EAPI_MAIN int
|
||||
elm_main(int argc, char **argv)
|
||||
{
|
||||
/* = win
|
||||
* |
|
||||
* \== bx
|
||||
* |
|
||||
* \== tb (toolbar)
|
||||
* | |
|
||||
* | \== items
|
||||
* | | ...
|
||||
* |
|
||||
* \== tb (table)
|
||||
* |
|
||||
* \== stuff
|
||||
*
|
||||
*/
|
||||
Evas_Object *main, *bx, *tb, *tb_box, *that, *menu;
|
||||
Evas_Object *ph1, *ph2, *ph3, *ph4;
|
||||
Elm_Object_Item *tb_it;
|
||||
Elm_Object_Item *menu_it;
|
||||
|
||||
win = elm_win_util_standard_add("minilauncher4slippi", "Minilauncher for Slippi");
|
||||
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
|
||||
elm_win_autodel_set(win, EINA_TRUE);
|
||||
|
||||
// BEGIN main
|
||||
main = elm_box_add(win);
|
||||
evas_object_size_hint_weight_set(main, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
||||
|
||||
elm_win_resize_object_add(win, main);
|
||||
evas_object_show(main);
|
||||
// END main
|
||||
|
||||
// BEGIN toolbar
|
||||
tb_box = elm_box_add(win);
|
||||
tb = elm_toolbar_add(tb_box);
|
||||
elm_box_horizontal_set(tb_box, EINA_TRUE);
|
||||
|
||||
elm_object_style_set(tb, "item_horizontal");
|
||||
elm_toolbar_homogeneous_set(tb, EINA_TRUE);
|
||||
elm_toolbar_shrink_mode_set(tb, ELM_TOOLBAR_SHRINK_MENU);
|
||||
evas_object_size_hint_weight_set(tb, 1.0, 0.0);
|
||||
evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, 0.0);
|
||||
evas_object_size_hint_weight_set(tb_box, 2.0, 0.0);
|
||||
evas_object_size_hint_align_set(tb_box, EVAS_HINT_FILL, 0.0);
|
||||
|
||||
tb_it = elm_toolbar_item_append(tb, "home", "Home", _tab_switch_cb, &tab_home);
|
||||
elm_toolbar_item_priority_set(tb_it, 100);
|
||||
|
||||
tb_it = elm_toolbar_item_append(tb, "media-seek-backward", "Replays", _tab_switch_cb, &tab_replays);
|
||||
elm_toolbar_item_priority_set(tb_it, -100);
|
||||
|
||||
tb_it = elm_toolbar_item_append(tb, "preferences-system", "Settings", _tab_switch_cb, &tab_config);
|
||||
elm_toolbar_item_priority_set(tb_it, 150);
|
||||
|
||||
tb_it = elm_toolbar_item_append(tb, "network-wireless", NULL, NULL, NULL);
|
||||
elm_toolbar_item_menu_set(tb_it, EINA_TRUE);
|
||||
elm_toolbar_item_priority_set(tb_it, -9999);
|
||||
elm_toolbar_menu_parent_set(tb, win);
|
||||
|
||||
that = elm_button_add(tb_box);
|
||||
elm_object_text_set(that, "Play");
|
||||
evas_object_smart_callback_add(that, "clicked", _launch_slippi_cb, that);
|
||||
Evas_Object* icon = elm_icon_add(win);
|
||||
elm_icon_standard_set(icon, "input-gaming");
|
||||
elm_object_part_content_set(that, "icon", icon);
|
||||
evas_object_show(that);
|
||||
elm_box_pack_end(tb_box, that);
|
||||
|
||||
elm_box_pack_end(tb_box, tb);
|
||||
|
||||
that = elm_clock_add(tb_box);
|
||||
evas_object_show(that);
|
||||
elm_box_pack_end(tb_box, that);
|
||||
|
||||
elm_box_pack_end(main, tb_box);
|
||||
|
||||
evas_object_show(tb_box);
|
||||
evas_object_show(tb);
|
||||
// END toolbar
|
||||
|
||||
mainer = elm_box_add(win);
|
||||
//evas_object_size_hint_weight_set(mainer, 0.0, EVAS_HINT_EXPAND);
|
||||
evas_object_size_hint_fill_set(mainer, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
evas_object_size_hint_weight_set(mainer, 1.0, 1.0);
|
||||
evas_object_size_hint_align_set(mainer, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
|
||||
|
||||
elm_box_pack_start(main, mainer);
|
||||
evas_object_show(mainer);
|
||||
tabs_init();
|
||||
|
||||
evas_object_resize(win, 520 * elm_config_scale_get(),
|
||||
300 * elm_config_scale_get());
|
||||
evas_object_show(win);
|
||||
|
||||
elm_run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
ELM_MAIN()
|
|
@ -0,0 +1,218 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "replay.h"
|
||||
|
||||
Evas_Object* tab_replays = NULL;
|
||||
char* replays_dir = "replays/";
|
||||
|
||||
struct replay
|
||||
{
|
||||
char* filename;
|
||||
char* p1;
|
||||
char* p1code;
|
||||
char* p2;
|
||||
char* p2code;
|
||||
int game_state;
|
||||
} replays[256] = {0};
|
||||
size_t replays_len = 0;
|
||||
|
||||
unsigned
|
||||
dec_uint_be(unsigned char* arr, size_t len)
|
||||
{
|
||||
unsigned res = 0;
|
||||
for (int i = len-1, j = 0; i >= 0; (--i, ++j))
|
||||
{
|
||||
res |= arr[i] << (j*8);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
long
|
||||
fsize(FILE* FP)
|
||||
{
|
||||
long _ = ftell(FP);
|
||||
fseek(FP, 0, SEEK_END);
|
||||
long new_size = ftell(FP);
|
||||
fseek(FP, _, SEEK_SET);
|
||||
return new_size;
|
||||
}
|
||||
|
||||
char*
|
||||
sstrstr(char* haystack, char* needle, size_t length)
|
||||
{
|
||||
size_t needle_length = strlen(needle);
|
||||
size_t i;
|
||||
for (i = 0; i < length; i++) {
|
||||
if (i + needle_length > length) {
|
||||
return NULL;
|
||||
}
|
||||
if (strncmp(&haystack[i], needle, needle_length) == 0) {
|
||||
return &haystack[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char*
|
||||
ubjson_search(unsigned char* buf, long length, char const* key, long* offset)
|
||||
{
|
||||
size_t key_len = strlen(key);
|
||||
char* start = sstrstr(buf, key, length);
|
||||
start += key_len;
|
||||
// Just 8 bits for now...
|
||||
uint8_t value_len = start[0];
|
||||
start++;
|
||||
|
||||
char* value = calloc(1, value_len + 1);
|
||||
memcpy(value, start, value_len);
|
||||
start += value_len;
|
||||
|
||||
if (offset)
|
||||
*offset = (long)start - (long)buf;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_replay(struct replay* rpy)
|
||||
{
|
||||
unsigned char buf[1024] = {0};
|
||||
char* filename;
|
||||
asprintf(&filename, "%s%s", replays_dir, rpy->filename);
|
||||
FILE* SLP = fopen(filename, "r");
|
||||
if (!SLP)
|
||||
{
|
||||
perror("fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
long filesize = fsize(SLP);
|
||||
|
||||
// Skip begin header and raw data
|
||||
fseek(SLP, 11, SEEK_CUR);
|
||||
fread(buf, 1, 4, SLP);
|
||||
fseek(SLP, dec_uint_be(buf, 4), SEEK_CUR);
|
||||
fseek(SLP, -6, SEEK_CUR);
|
||||
fread(buf, 1, 1, SLP);
|
||||
fseek(SLP, 5, SEEK_CUR);
|
||||
rpy->game_state = buf[0];
|
||||
|
||||
// debug
|
||||
long length = filesize - ftell(SLP);
|
||||
fread(buf, 1, length, SLP);
|
||||
long off;
|
||||
char* bufx = buf;
|
||||
char* p1name = ubjson_search(bufx, length, "netplaySU", &off);
|
||||
length -= off; bufx += off;
|
||||
char* p1code = ubjson_search(bufx, length, "codeSU", &off);
|
||||
length -= off; bufx += off;
|
||||
|
||||
char* p2name = ubjson_search(bufx, length, "netplaySU", &off);
|
||||
length -= off; bufx += off;
|
||||
char* p2code = ubjson_search(bufx, length, "codeSU", &off);
|
||||
length -= off; bufx += off;
|
||||
|
||||
rpy->p1 = p1name;
|
||||
rpy->p1code = p1code;
|
||||
rpy->p2 = p2name;
|
||||
rpy->p2code = p2code;
|
||||
|
||||
printf("Reading %s\n", filename);
|
||||
abort:
|
||||
fclose(SLP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
recurse_replay_files()
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
dp = opendir(replays_dir);
|
||||
if (dp != NULL)
|
||||
{
|
||||
while ((ep = readdir(dp)) != NULL)
|
||||
{
|
||||
if (ep->d_name && ep->d_name[0] != '.')
|
||||
{
|
||||
struct replay* rpy = replays + replays_len++;
|
||||
rpy->filename = strdup(ep->d_name);
|
||||
// End
|
||||
parse_replay(rpy);
|
||||
puts(ep->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char const*
|
||||
gameend2str(int code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case 0: return "Unresolved";
|
||||
case 1: return "TIME!";
|
||||
case 2: return "GAME!";
|
||||
case 3: return "Resolved.";
|
||||
case 7: return "No Contest.";
|
||||
}
|
||||
}
|
||||
|
||||
static char*
|
||||
replays_strings(void* data, Evas_Object* obj, const char* part)
|
||||
{
|
||||
long idx = data;
|
||||
// Check this is text for the part we're expecting
|
||||
if (strcmp(part, "elm.text") == 0)
|
||||
{
|
||||
char* c;
|
||||
asprintf(&c, "%s | %s [%s] Vs. %s [%s]", gameend2str(replays[idx].game_state),
|
||||
replays[idx].p1, replays[idx].p1code,
|
||||
replays[idx].p2, replays[idx].p2code);
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_item_select_cb(void *data, Evas_Object *obj, void *event_info)
|
||||
{
|
||||
long idx = data;
|
||||
printf("sel item data [%p] on genlist obj [%p], item pointer [%p]\n",
|
||||
data, obj, event_info);
|
||||
}
|
||||
|
||||
void
|
||||
tab_replays_setup(Evas_Object* parent)
|
||||
{
|
||||
tab_replays = elm_genlist_add(parent);
|
||||
elm_genlist_homogeneous_set(tab_replays, EINA_TRUE);
|
||||
evas_object_resize(tab_replays, 40, 40);
|
||||
Elm_Genlist_Item_Class *_itc = elm_genlist_item_class_new();
|
||||
_itc->item_style = "default";
|
||||
_itc->func.text_get = replays_strings;
|
||||
_itc->func.content_get = NULL;
|
||||
_itc->func.state_get = NULL;
|
||||
_itc->func.del = NULL;
|
||||
|
||||
recurse_replay_files();
|
||||
|
||||
for (int i = 0; i < replays_len; ++i)
|
||||
{
|
||||
elm_genlist_item_append(tab_replays,
|
||||
_itc,
|
||||
i, // Item data
|
||||
NULL, // Parent item for trees, NULL if none
|
||||
ELM_GENLIST_ITEM_NONE, // Item type; this is the common one
|
||||
_item_select_cb, // Callback on selection of the item
|
||||
(long)i // Data for that callback function
|
||||
);
|
||||
}
|
||||
|
||||
evas_object_size_hint_align_set(tab_replays, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
||||
|
||||
}
|
Loading…
Reference in New Issue