diff --git a/.github/workflows/test.sh b/.github/workflows/test.sh new file mode 100644 index 0000000..4104110 --- /dev/null +++ b/.github/workflows/test.sh @@ -0,0 +1,10 @@ +set -e + +models=("fuji_x_h1" "fuji_x_a2" "fuji_x_t20" "fuji_x_t2" "fuji_x_s10" "fuji_x_f10" "fuji_x30") + +for model in "${models[@]}"; do + ~/vcam/vcam $model --local & + pid=$! + desktop/fudge.out -tw + kill $pid +done diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 95e926f..037919c 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -32,4 +32,4 @@ jobs: - name: Compile desktop run: cd desktop && make TARGET=l fudge.out - name: Run desktop unit test - run: cd desktop && ./fudge.out -tw + run: bash .github/workflows/test.sh diff --git a/desktop/Makefile b/desktop/Makefile index 1c0650c..85099cd 100644 --- a/desktop/Makefile +++ b/desktop/Makefile @@ -1,6 +1,6 @@ FUDGE = ../lib -OBJ := main.o ui.o +OBJ := main.o ui.o jank.o CAMLIB_CORE := transport.o operations.o packet.o enums.o data.o enum_dump.o lib.o canon.o liveview.o bind.o ml.o conv.o generic.o canon_adv.o ifeq ($(TARGET),l) @@ -13,7 +13,7 @@ OBJ += $(addprefix camlib-,$(CAMLIB_CORE)) OBJ += $(addprefix camlua-,lua.o runtime.o) OBJ += $(addprefix camluajson-,lua_cjson.o strbuf.o) -FUDGE_CORE := fuji.o tester.o viewer.o data.o net.o discovery.o exif.o uilua.o fuji_usb.o +FUDGE_CORE := fuji.o tester.o data.o net.o discovery.o exif.o uilua.o fuji_usb.o OBJ += $(addprefix fudge-,$(FUDGE_CORE)) CAMLIB_DIR := ../lib/camlib @@ -58,4 +58,4 @@ fudge-%.o: $(FUDGE)/%.c -include $(CAMLIB_DIR)/src/*.d $(CAMLIB_DIR)/lua/*.d $(CAMLIB_DIR)/lua/lua-cjson/*.d $(FUDGE)/*.d clean: - $(RM) *.o $(LIB_OBJ) main *.exe *.res + $(RM) *.o $(LIB_OBJ) main *.exe *.res *.out diff --git a/desktop/desktop.h b/desktop/desktop.h index dad4b62..ac13c69 100644 --- a/desktop/desktop.h +++ b/desktop/desktop.h @@ -1 +1,7 @@ +void network_init(void); int fudge_main_ui(void); + +int fuji_test_discovery(struct PtpRuntime *r); + +int fuji_test_filesystem(struct PtpRuntime *r); +int fuji_test_setup(struct PtpRuntime *r); diff --git a/desktop/jank.c b/desktop/jank.c new file mode 100644 index 0000000..4d38e89 --- /dev/null +++ b/desktop/jank.c @@ -0,0 +1,259 @@ +// Jank code from testing Fuji PTP +// Their protocols SUCK! +#include +#include +#include +#include +#include +#include +#ifdef WIN32 + #include + #include +#else + #include + #include +#endif +#include +#include +#include +#include +#include "desktop.h" + +// Trying to set camera properties like Fuji tetherapp does. +int fudge_test(struct PtpRuntime *r) { + if (ptp_device_init(r)) { + puts("Device connection error"); + return 0; + } + + int rc; + + ptp_open_session(r); + +#if 0 + struct PtpPropDesc pd; + rc = ptp_get_prop_desc(r, 0xd20b, &pd); + + printf("Prop data type: %d\n", ptp_get_payload_length(r)); + + rc = ptp_get_prop_value(r, 0xD21c); + if (rc) return rc; + + printf("Prop code: %x\n", ptp_parse_prop_value(r)); +#endif + +/* +Fuji Wireless/USB Tether: +- PtpGetPropValue must be called after PtpSetPropValue +- If menu (or quick menu) is open, PtpSetPropValue will return DeviceBusy +- PtpDeviceInfo seems to include some data to indicate what properties have changed (bitmap?) +- PtpDeviceInfo FunctionalState is 0x02a8 (can't remember, vendor?) +- AFAIK gphoto people have not documented this mode. There were a few github issues about brokenness. +*/ + +// char buffer[90000]; +// int i = 0; +// while (1) { +// ptp_set_prop_value(r, 0x5015, entries[i % 8]); +// i++; +// ptp_get_prop_value(r, 0x5015); +// +// struct PtpDeviceInfo di; +// rc = ptp_get_device_info(r, &di); +// if (rc) return rc; +// ptp_device_info_json(&di, buffer, sizeof(buffer)); +// printf("%s\n", buffer); +// +// ptp_get_prop_value(r, 0xd20b); +// //printf("%X: %d\n", 0xd20b, ptp_parse_prop_value(r)); +// ptp_get_prop_value(r, 0xd212); +// //printf("%X: %d\n", 0xd212, ptp_parse_prop_value(r)); +// +// +// usleep(1000 * 1000 * 2); +// } + + return 0; +} + +// Fuji sets this property while doing pc autosave +// guess: client tells camera what photos are already downloaded +int _fuji_d228(struct PtpRuntime *r) { + char buffer[64]; + int s = 0; + s += ptp_write_u8(buffer + s, 6); + s += ptp_write_u32(buffer + s, 0x0020); + s += ptp_write_u32(buffer + s, 0x0030); + s += ptp_write_u32(buffer + s, 0x002f); + s += ptp_write_u32(buffer + s, 0x0036); + s += ptp_write_u32(buffer + s, 0x0030); + s += ptp_write_u32(buffer + s, 0x0000); + return ptp_set_prop_value_data(r, 0xd228, buffer, s); +} + +/* +- GetPartialObject and GetObjectInfo both refuse to send response if conditions are wrong +- Most of the time we can recover +- Is there a way to determine if we shouldn't download an image? No, ObjectInfo is basically the same. +- The max doesn't seem to matter. +- It works fine if we download the entire image. If we don't, or try and skip to the end, the next getpartialobject/getobjectinfo returns no +response. + +Conclusion: GetPartialObject tracks the number of bytes read, and freaks out when attemping another object with previous unfinished +*/ +int fuji_autosave_thumb(struct PtpRuntime *r, int handle) { + int rc; + + tester_log("Object #%d...", handle); +#if 0 + struct PtpObjectInfo oi; + r->wait_for_response = 1; + rc = ptp_get_object_info(r, handle, &oi); + if (rc == PTP_CHECK_CODE) { + return 0; + } + if (rc) { + tester_fail("Failed to get object info: %d", rc); + return 0; + } else { + tester_log("Got object info"); + } + + char buffer[1024]; + ptp_object_info_json(&oi, buffer, sizeof(buffer)); + app_print(buffer); +#endif + +// rc = ptp_get_partial_object(r, handle, 0, 0x0); +// rc = ptp_get_partial_object(r, handle, 0, 0x0); + +// _fuji_d228(r); + + //rc = ptp_set_prop_value16(r, PTP_PC_FUJI_NoCompression, 1); + + rc = fuji_get_events(r); + if (rc) return rc; + + + int max = 0x100000/128; + +// if (handle == 15 || handle == 8 || handle == 7) max = 0x100000; + + r->wait_for_response = 2; + rc = ptp_get_partial_object(r, handle, 0, max); + if (rc == PTP_IO_ERR) return rc; + //rc = ptp_get_partial_object(r, handle, 0xfffffff, 0xfffffff); + + rc = ptp_get_partial_object(r, handle, max, max * 2); + if (rc == PTP_IO_ERR) return rc; + + rc = fuji_get_events(r); + if (rc) return rc; + rc = fuji_get_events(r); + if (rc) return rc; + rc = fuji_get_events(r); + if (rc) return rc; + rc = fuji_get_events(r); + if (rc) return rc; + + /* + 300-200 + get event x1 + max = 0x100000/32 + partial object x2 + get event x4 + Took 67.956009 seconds + - x4 -> x1: crash + - x1/x3: 63.188999 + - x1/x2: 56.750000 + - x1/x1: crash + - getobjinfo+x1/x3: 73... without getobjectinfo, 62.955002 + - get event x1/x1, usleep 100ms: 61.487000 + - 0 get event, 300ms: crash + */ + + // + +// rc = ptp_get_partial_object(r, handle | (1 << 31), 0, 0x0); +// rc = ptp_get_partial_object(r, handle | (1 << 31), 0, 0x0); + +// rc = fuji_get_events(r); +// if (rc) return rc; + + //rc = ptp_get_partial_object(r, handle, 0x0fffffff, 0x0); + + //rc = ptp_get_partial_object(r, handle, oi.compressed_size - 0x100000, 0x100000); + //if (rc == PTP_IO_ERR) return rc; + + //rc = ptp_set_prop_value16(r, PTP_PC_FUJI_NoCompression, 1); + //rc = fuji_get_events(r); + + return 0; +} + +/* +Fuji Wireless Tether property setting: +- PtpGetPropValue must be called after PtpSetPropValue +- If menu (or quick menu) is open, PtpSetPropValue will return DeviceBusy +- PtpDeviceInfo seems to include some data to indicate what properties have changed +*/ +static int dump_prop(struct PtpRuntime *r) { + struct PtpPropDesc pd; + int rc = ptp_get_prop_desc(r, 0x5015, &pd); + if (rc) return rc; + char buffer[70000]; + ptp_prop_desc_json(&pd, buffer, sizeof(buffer)); + printf("%s\n", buffer); + return 0; +} + +int fuji_test_discovery(struct PtpRuntime *r) { + struct DiscoverInfo info = {0}; + network_init(); + + int sock = socket(AF_INET, SOCK_DGRAM, 0); + + int rc = fuji_discover_thread(&info, "Fudge (desktop)", NULL); + if (rc == FUJI_D_REGISTERED) { + plat_dbg("Registered %s %s", info.camera_name, info.camera_model); + } else if (rc == FUJI_D_GO_PTP) { + usleep(100000); // TODO: Kind of have to wait before connecting + + printf("connecting to %s:%d\n", info.camera_ip, info.camera_port); + if (ptpip_connect(r, info.camera_ip, info.camera_port)) { + printf("Error connecting to %s:%d\n", info.camera_ip, info.camera_port); + return 0; + } + + fuji_reset_ptp(r); + r->connection_type = PTP_IP_USB; + fuji_get(r)->transport = info.transport; + + //rc = fujitether_setup(r); + rc = fuji_setup(r, info.camera_ip); + if (rc) return rc; + + float startTime = (float)clock()/CLOCKS_PER_SEC; + + int max = fuji_get(r)->num_objects; + for (int i = max; i != max - 100; i--) { + rc = fuji_autosave_thumb(r, i); + if (rc) { + plat_dbg("Failed autosave thumb"); + return rc; + } + } + + float endTime = (float)clock()/CLOCKS_PER_SEC; + + plat_dbg("Took %f seconds", endTime - startTime); + + int16_t entries[] = {0, 10, 20, 30}; + + ptpip_close(r); + } else { + plat_dbg("Response code: %d\n", rc); + } + + return -1; +} diff --git a/desktop/main.c b/desktop/main.c index 41c054e..4e90600 100644 --- a/desktop/main.c +++ b/desktop/main.c @@ -1,4 +1,3 @@ -// Test basic opcode, get device properties #include #include #include @@ -23,31 +22,12 @@ struct PtpRuntime *ptp_get() { return ptp; } -int fuji_test_filesystem(struct PtpRuntime *r); -int fuji_test_setup(struct PtpRuntime *r); - -void ptp_report_error(struct PtpRuntime *r, const char *reason, int code) { - plat_dbg("Kill switch: %d tid: %d\n", r->io_kill_switch, getpid()); - if (r->io_kill_switch) return; - r->io_kill_switch = 1; - - if (r->connection_type == PTP_IP_USB) { - ptpip_close(r); - } else if (r->connection_type == PTP_USB) { - ptp_close(r); - } - - fuji_reset_ptp(r); - - if (reason == NULL) { - if (code == PTP_IO_ERR) { - app_print("Disconnected: IO Error"); - } else { - app_print("Disconnected: Runtime error"); - } - } else { - app_print("Disconnected: %s", reason); - } +void network_init() { +#ifdef WIN32 + // Windows wants to init this thread for socket stuff + WSADATA wsaData = {0}; + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif } void ptp_verbose_log(char *fmt, ...) { @@ -77,146 +57,43 @@ void plat_dbg(char *fmt, ...) { putchar('\n'); } -void tester_log(char *fmt, ...) { - char buffer[512]; - va_list args; - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - printf("LOG: %s\n", buffer); -} - -void tester_fail(char *fmt, ...) { - char buffer[512]; - va_list args; - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - printf("FAIL: %s\n", buffer); -} - int app_bind_socket_wifi(int sockfd) { return 0; } -void app_increment_progress_bar(int read) { - -} - -int fudge_test(struct PtpRuntime *r) { - if (ptp_device_init(r)) { - puts("Device connection error"); - return 0; - } - - int rc; - - ptp_open_session(r); - -#if 0 - struct PtpPropDesc pd; - rc = ptp_get_prop_desc(r, 0xd20b, &pd); - - printf("Prop data type: %d\n", ptp_get_payload_length(r)); - - rc = ptp_get_prop_value(r, 0xD21c); - if (rc) return rc; - - printf("Prop code: %x\n", ptp_parse_prop_value(r)); -#endif - -/* -Fuji Wireless/USB Tether: -- PtpGetPropValue must be called after PtpSetPropValue -- If menu (or quick menu) is open, PtpSetPropValue will return DeviceBusy -- PtpDeviceInfo seems to include some data to indicate what properties have changed (bitmap?) -- PtpDeviceInfo FunctionalState is 0x02a8 -- AFAIK gphoto people have not documented this mode -*/ - char buffer[90000]; - int i = 0; - while (1) { - ptp_set_prop_value(r, 0x5015, entries[i % 8]); - i++; - ptp_get_prop_value(r, 0x5015); - - struct PtpDeviceInfo di; - rc = ptp_get_device_info(r, &di); - if (rc) return rc; - ptp_device_info_json(&di, buffer, sizeof(buffer)); - printf("%s\n", buffer); - - ptp_get_prop_value(r, 0xd20b); - //printf("%X: %d\n", 0xd20b, ptp_parse_prop_value(r)); - ptp_get_prop_value(r, 0xd212); - //printf("%X: %d\n", 0xd212, ptp_parse_prop_value(r)); - - - usleep(1000 * 1000 * 2); - } - +int app_check_thread_cancel(void) { + // TODO: check signal return 0; } -void *fudge_backup_test(void *arg) { +void *fudge_usb_connect(void *arg) { struct PtpRuntime *r = ptp_get(); int rc; if (ptp_device_init(r)) { puts("Device connection error"); return 0; } + fuji_reset_ptp(r); - /* - For some bizarre reason, Fuji X Acquire ended up doing something like: - struct PtpDeviceInfo di; - for (int i = 0; i < 20; i++) { - rc = ptp_get_device_info(r, &di); - rc = ptp_get_prop_value(r, 0xd20b); - } - struct PtpObjectInfo oi; - rc = ptp_get_object_info(r, 0, &oi); - rc = ptp_get_object_info(r, 0, &oi); - Before running GetObject. I'm guessing they have a background thread running GetDeviceInfo - and GetPropValue 0xd20b and then I must have actually downloaded my settings a while after. - */ - - // struct PtpDeviceInfo di; - // for (int i = 0; i < 20; i++) { - // rc = ptp_get_device_info(r, &di); - // rc = ptp_get_prop_value(r, 0xd20b); - // } - - struct PtpObjectInfo oi; - rc = ptp_get_object_info(r, 0, &oi); - rc = ptp_get_object_info(r, 0, &oi); - - char buffer[1024]; - ptp_object_info_json(&oi, buffer, sizeof(buffer)); - app_print(buffer); - - app_print("Hello, WOrld\n"); - - rc = ptp_get_object(r, 0); - app_print("Downloaded payload %d bytes\n", ptp_get_payload_length(r)); + app_print("Hello, World"); pthread_exit(NULL); return NULL; } int fudge_test_wifi(struct PtpRuntime *r) { -#ifdef WIN32 - // Windows wants to init this thread for socket stuff - WSADATA wsaData = {0}; - WSAStartup(MAKEWORD(2, 2), &wsaData); -#endif + network_init(); int rc = 0; - char *ip_addr = "192.168.1.39"; + char *ip_addr = "0.0.0.0"; r->connection_type = PTP_IP_USB; if (ptpip_connect(r, ip_addr, FUJI_CMD_IP_PORT)) { printf("Error connecting to %s:%d\n", ip_addr, FUJI_CMD_IP_PORT); return 0; } + fuji_reset_ptp(r); + r->connection_type = PTP_IP_USB; + fuji_get(r)->transport = FUJI_FEATURE_WIRELESS_COMM; rc = fuji_test_setup(r); if (rc) return rc; @@ -224,99 +101,14 @@ int fudge_test_wifi(struct PtpRuntime *r) { rc = fuji_test_filesystem(r); if (rc) return rc; - ptp_close_session(r); + rc = ptp_close_session(r); + if (rc) return rc; ptpip_close(r); return 0; } -int _fuji_d228(struct PtpRuntime *r) { - char buffer[64]; - int s = 0; - s += ptp_write_u8(buffer + s, 6); - s += ptp_write_u32(buffer + s, 0x0020); - s += ptp_write_u32(buffer + s, 0x0030); - s += ptp_write_u32(buffer + s, 0x002f); - s += ptp_write_u32(buffer + s, 0x0036); - s += ptp_write_u32(buffer + s, 0x0030); - s += ptp_write_u32(buffer + s, 0x0000); - return ptp_set_prop_value_data(r, 0xd228, buffer, s); -} - -int fuji_autosave_thumb(struct PtpRuntime *r, int handle) { - int rc; - - tester_log("Object #%d...", handle); -#if 0 - struct PtpObjectInfo oi; - r->wait_for_response = 1; - rc = ptp_get_object_info(r, handle, &oi); - if (rc == PTP_CHECK_CODE) { - return 0; - } - if (rc) { - tester_fail("Failed to get object info: %d", rc); - return 0; - } else { - tester_log("Got object info"); - } - - char buffer[1024]; - ptp_object_info_json(&oi, buffer, sizeof(buffer)); - app_print(buffer); -#endif - -// rc = ptp_get_partial_object(r, handle, 0, 0x0); -// rc = ptp_get_partial_object(r, handle, 0, 0x0); - -// _fuji_d228(r); - - rc = ptp_set_prop_value16(r, PTP_PC_FUJI_NoCompression, 0); - - int max = 0x100000/32; - -// if (handle == 15 || handle == 8 || handle == 7) max = 0x100000; - - r->wait_for_response = 2; - rc = ptp_get_partial_object(r, handle, 0, max); - if (rc == PTP_IO_ERR) return rc; - //rc = ptp_get_partial_object(r, handle, 0xfffffff, 0xfffffff); - - rc = fuji_get_events(r); - if (rc) return rc; - rc = fuji_get_events(r); - if (rc) return rc; - - // - -// rc = ptp_get_partial_object(r, handle | (1 << 31), 0, 0x0); -// rc = ptp_get_partial_object(r, handle | (1 << 31), 0, 0x0); - -// rc = fuji_get_events(r); -// if (rc) return rc; - - //rc = ptp_get_partial_object(r, handle, 0x0fffffff, 0x0); - - //rc = ptp_get_partial_object(r, handle, oi.compressed_size - 0x100000, 0x100000); - //if (rc == PTP_IO_ERR) return rc; - - rc = ptp_set_prop_value16(r, PTP_PC_FUJI_NoCompression, 0); - - return 0; -} - -/* -- GetPartialObject and GetObjectInfo both refuse to send response if conditions are wrong -- Most of the time we can recover -- Is there a way to determine if we shouldn't download an image? No, ObjectInfo is basically the same. -- The max doesn't seem to matter. -- It works fine if we download the entire image. If we don't, or try and skip to the end, the next getpartialobject/getobjectinfo returns no -response. - -Conclusion: GetPartialObject tracks the number of bytes read, and freaks out when do another object with it unfinished -*/ - int fuji_discover_ask_connect(void *arg, struct DiscoverInfo *info) { // Ask if we want to connect? return 1; @@ -326,114 +118,16 @@ int fuji_discovery_check_cancel(void *arg) { return 0; } -int fuji_test_discovery(struct PtpRuntime *r) { - struct DiscoverInfo info = {0}; - -#ifdef WIN32 - // Windows wants to init this thread for socket stuff - WSADATA wsaData = {0}; - WSAStartup(MAKEWORD(2, 2), &wsaData); -#endif - - int sock = socket(AF_INET, SOCK_DGRAM, 0); - - int rc = fuji_discover_thread(&info, "Fudge (desktop)", NULL); - if (rc == FUJI_D_REGISTERED) { - plat_dbg("Registered %s %s", info.camera_name, info.camera_model); - } else if (rc == FUJI_D_GO_PTP) { - usleep(100000); // TODO: Kind of have to wait before connecting - - fuji_reset_ptp(r); - r->connection_type = PTP_IP_USB; - fuji_get(r)->transport = info.transport; - printf("connecting to %s:%d\n", info.camera_ip, info.camera_port); - if (ptpip_connect(r, info.camera_ip, info.camera_port)) { - printf("Error connecting to %s:%d\n", info.camera_ip, info.camera_port); - return 0; - } - - if (info.transport == FUJI_FEATURE_WIRELESS_COMM) { - rc = fuji_setup(r, info.camera_ip); - } else if (info.transport == FUJI_FEATURE_WIRELESS_TETHER) { - rc = fujitether_setup(r); - } - - if (rc) return rc; - -// ptp_get_thumbnail(r, 10); - -// for (int i = 0; i < 100; i++) { -// ptp_get_prop_value(r, 0xD001 + i); -// printf("%X %d\n", 0xD001 + i, ptp_parse_prop_value(r)); -// } - - struct PtpPropDesc pd; - rc = ptp_get_prop_desc(r, 0x5015, &pd); - if (rc) return rc; - char buffer[70000]; - ptp_prop_desc_json(&pd, buffer, sizeof(buffer)); - printf("%s\n", buffer); - -// ptp_get_prop_value(r, 0xD154); -// printf("%X: %d\n", 0xD154, ptp_parse_prop_value(r)); - //ptp_get_prop_value(r, 0xd023); - //printf("%X: %d\n", 0xd023, ptp_parse_prop_value(r)); - //ptp_set_prop_value(r, 0xd023, 1); - - - int16_t entries[] = {0, 10, 20, 30}; - -/* -Fuji Wireless Tether: -- PtpGetPropValue must be called after PtpSetPropValue -- If menu (or quick menu) is open, PtpSetPropValue will return DeviceBusy -- PtpDeviceInfo seems to include some data to indicate what properties have changed -*/ - - int i = 0; - while (1) { - ptp_set_prop_value(r, 0x5015, entries[i % 8]); - i++; - ptp_get_prop_value(r, 0x5015); - - struct PtpDeviceInfo di; - rc = ptp_get_device_info(r, &di); - if (rc) return rc; - ptp_device_info_json(&di, buffer, sizeof(buffer)); - printf("%s\n", buffer); - - ptp_get_prop_value(r, 0xd20b); - //printf("%X: %d\n", 0xd20b, ptp_parse_prop_value(r)); - ptp_get_prop_value(r, 0xd212); - //printf("%X: %d\n", 0xd212, ptp_parse_prop_value(r)); - - - usleep(1000 * 1000 * 2); - } - - // 65526 - -// for (int i = 51; i > 0; i--) { -// rc = fuji_autosave_thumb(r, i); -// if (rc) return rc; -// } - - ptpip_close(r); - } else { - plat_dbg("Response code: %d\n", rc); - } - - return -1; -} - int main(int argc, char **argv) { ptp = ptp_new(PTP_USB); for (int i = 0; i < argc; i++) { if (!strcmp(argv[i], "-tw")) { - return fudge_test_wifi(ptp); + int rc = fudge_test_wifi(ptp); + plat_dbg("Result: %d\n", rc); + return rc; } else if (!strcmp(argv[i], "-tu")) { - return fudge_test(ptp); + //return fudge_test(ptp); } else if (!strcmp(argv[i], "-d")) { fuji_test_discovery(ptp); return 1; diff --git a/desktop/ui.c b/desktop/ui.c index c580b9f..4c46e78 100644 --- a/desktop/ui.c +++ b/desktop/ui.c @@ -1,4 +1,4 @@ -// #include +#include #include #include #include @@ -25,15 +25,52 @@ struct PtpRuntime *luaptp_get_runtime(lua_State *L) { return ptp_get(); } -void ui_send_text(char *key, char *value, ...) { +void app_send_cam_name(const char *name) { if (!app.is_opened) { return; } - if (!strcmp(key, "cam_name")) { - char buffer[64]; - sprintf(buffer, "Fudge - %s", value); - uiWindowSetTitle(app.main_win, buffer); - } + + char buffer[64]; + sprintf(buffer, "Fudge - %s", name); + uiWindowSetTitle(app.main_win, buffer); +} + +void fuji_discovery_update_progress(void *arg, int progress) { + // ... +} + +void app_get_file_path(char buffer[256], const char *filename) { + snprintf(buffer, 256, "%s", filename); +} + +void app_downloading_file(const struct PtpObjectInfo *oi) { + // ... +} + +void app_downloaded_file(const struct PtpObjectInfo *oi, const char *path) { + // ... +} + +void app_increment_progress_bar(int read) { + // ... +} + +void tester_log(char *fmt, ...) { + char buffer[512]; + va_list args; + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + printf("LOG: %s\n", buffer); +} + +void tester_fail(char *fmt, ...) { + char buffer[512]; + va_list args; + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + printf("FAIL: %s\n", buffer); } static void print_thread(char *buffer) { @@ -142,12 +179,12 @@ static uiControl *files_tab() { return uiControl(t); } -extern void *fudge_backup_test(void *arg); +extern void *fudge_usb_connect(void *arg); static void usb_connect(uiButton *btn, void *data) { pthread_t thread; - pthread_create(&thread, 0, fudge_backup_test, NULL); + pthread_create(&thread, 0, fudge_usb_connect, NULL); } int cam_lua_setup(lua_State *L) { diff --git a/desktop/win.res b/desktop/win.res deleted file mode 100644 index eb56b3b..0000000 Binary files a/desktop/win.res and /dev/null differ diff --git a/lib/progress.c b/lib/progress.c deleted file mode 100644 index c3f5d3d..0000000 --- a/lib/progress.c +++ /dev/null @@ -1,44 +0,0 @@ -// Progress bar / IO monitoring backend -// Copyright 2024 by Daniel C (https://github.com/petabyt/camlib) -#include -#include -#include -#include "app.h" -#include "backend.h" - -static int last_p = 0; - -void app_increment_progress_bar(int read) { - if (backend.progress_bar == NULL) { - return; - } - - backend.download_progress += read; - - int n = (((double)backend.download_progress) / (double)backend.download_size * 100.0); - if (last_p != n) { - if (n > 100) return; - - JNIEnv *env = get_jni_env(); - - jmethodID method = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, backend.progress_bar), "setProgress", "(I)V"); - (*env)->CallVoidMethod(env, backend.progress_bar, method, n); - } - last_p = n; -} - -JNI_FUNC(jboolean, cSetProgressBarObj)(JNIEnv *env, jobject thiz, jobject pg, jint size) { - static clock_t tm; - if (pg == NULL) { - plat_dbg("Time taken to download: %f", (double)(clock() - tm) / CLOCKS_PER_SEC); - (*env)->DeleteGlobalRef(env, backend.progress_bar); - backend.progress_bar = NULL; - return 0; - } - tm = clock(); - last_p = 0; - backend.download_size = size; - backend.download_progress = 0; - backend.progress_bar = (*env)->NewGlobalRef(env, pg); - return 0; -}