forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			218 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			218 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | #include "loader.h"
 | ||
|  | 
 | ||
|  | #include <kinc/audio1/sound.h>
 | ||
|  | #include <kinc/image.h>
 | ||
|  | #include <kinc/io/filereader.h>
 | ||
|  | #include <kinc/threads/event.h>
 | ||
|  | #include <kinc/threads/mutex.h>
 | ||
|  | #include <kinc/threads/thread.h>
 | ||
|  | 
 | ||
|  | #define STB_DS_IMPLEMENTATION
 | ||
|  | #include "stb_ds.h"
 | ||
|  | 
 | ||
|  | #include <assert.h>
 | ||
|  | 
 | ||
|  | static kinc_thread_t thread; | ||
|  | static kinc_event_t event; | ||
|  | static kinc_mutex_t loading_mutex; | ||
|  | static kinc_mutex_t loaded_mutex; | ||
|  | 
 | ||
|  | static kha_index_t next_index = 1; | ||
|  | 
 | ||
|  | static kha_file_reference_t *loading_files = NULL; | ||
|  | static kha_file_reference_t *loaded_files = NULL; | ||
|  | 
 | ||
|  | static bool string_ends_with(char *str, const char *end) { | ||
|  | 	size_t str_len = strlen(str); | ||
|  | 	size_t end_len = strlen(end); | ||
|  | 	if (end_len > str_len) { | ||
|  | 		return false; | ||
|  | 	} | ||
|  | 	return strcmp(&str[str_len - end_len], end) == 0; | ||
|  | } | ||
|  | 
 | ||
|  | static void run(void *param) { | ||
|  | 	for (;;) { | ||
|  | 		kinc_event_wait(&event); | ||
|  | 
 | ||
|  | 		bool has_next = false; | ||
|  | 		kha_file_reference_t next; | ||
|  | 
 | ||
|  | 		kinc_mutex_lock(&loading_mutex); | ||
|  | 		if (arrlen(loading_files) > 0) { | ||
|  | 			has_next = true; | ||
|  | 			next = arrpop(loading_files); | ||
|  | 		} | ||
|  | 		else { | ||
|  | 			kinc_event_reset(&event); | ||
|  | 		} | ||
|  | 		kinc_mutex_unlock(&loading_mutex); | ||
|  | 
 | ||
|  | 		while (has_next) { | ||
|  | 			switch (next.type) { | ||
|  | 			case KHA_FILE_TYPE_BLOB: { | ||
|  | 				kinc_file_reader_t reader; | ||
|  | 				if (kinc_file_reader_open(&reader, next.name, KINC_FILE_TYPE_ASSET)) { | ||
|  | 					next.data.blob.size = kinc_file_reader_size(&reader); | ||
|  | 					next.data.blob.bytes = (uint8_t *)malloc(next.data.blob.size); | ||
|  | 					kinc_file_reader_read(&reader, next.data.blob.bytes, next.data.blob.size); | ||
|  | 					kinc_file_reader_close(&reader); | ||
|  | 				} | ||
|  | 				else { | ||
|  | 					next.error = true; | ||
|  | 				} | ||
|  | 				break; | ||
|  | 			} | ||
|  | 			case KHA_FILE_TYPE_IMAGE: { | ||
|  | 				kinc_image_t image; | ||
|  | 				size_t size = kinc_image_size_from_file(next.name); | ||
|  | 				if (size > 0) { | ||
|  | 					void *data = malloc(size); | ||
|  | 					if (kinc_image_init_from_file(&image, data, next.name) != 0) { | ||
|  | 						next.data.image.image = image; | ||
|  | 					} | ||
|  | 					else { | ||
|  | 						free(data); | ||
|  | 						next.error = true; | ||
|  | 					} | ||
|  | 				} | ||
|  | 				else { | ||
|  | 					next.error = true; | ||
|  | 				} | ||
|  | 				break; | ||
|  | 			} | ||
|  | 			case KHA_FILE_TYPE_SOUND: { | ||
|  | 				memset(&next.data.sound, 0, sizeof(next.data.sound)); | ||
|  | 				if (string_ends_with(next.name, ".ogg")) { | ||
|  | 					kinc_file_reader_t reader; | ||
|  | 					if (kinc_file_reader_open(&reader, next.name, KINC_FILE_TYPE_ASSET)) { | ||
|  | 						next.data.sound.size = kinc_file_reader_size(&reader); | ||
|  | 						next.data.sound.compressed_samples = (uint8_t *)malloc(next.data.sound.size); | ||
|  | 						kinc_file_reader_read(&reader, next.data.sound.compressed_samples, kinc_file_reader_size(&reader)); | ||
|  | 						kinc_file_reader_close(&reader); | ||
|  | 					} | ||
|  | 					else { | ||
|  | 						next.error = true; | ||
|  | 					} | ||
|  | 				} | ||
|  | 				else { | ||
|  | 					kinc_a1_sound_t *sound = kinc_a1_sound_create(next.name); | ||
|  | 					if (sound != NULL) { | ||
|  | 						next.data.sound.size = sound->size * 2; | ||
|  | 						next.data.sound.samples = (float *)malloc(next.data.sound.size * sizeof(float)); | ||
|  | 						for (int i = 0; i < sound->size; ++i) { | ||
|  | 							next.data.sound.samples[i * 2 + 0] = (float)(sound->left[i] / 32767.0); | ||
|  | 							next.data.sound.samples[i * 2 + 1] = (float)(sound->right[i] / 32767.0); | ||
|  | 						} | ||
|  | 						next.data.sound.channels = sound->format.channels; | ||
|  | 						next.data.sound.sample_rate = sound->format.samples_per_second; | ||
|  | 						next.data.sound.length = | ||
|  | 						    (sound->size / (sound->format.bits_per_sample / 8) / sound->format.channels) / (float)sound->format.samples_per_second; | ||
|  | 						kinc_a1_sound_destroy(sound); | ||
|  | 					} | ||
|  | 					else { | ||
|  | 						next.error = true; | ||
|  | 					} | ||
|  | 				} | ||
|  | 				break; | ||
|  | 			} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			kinc_mutex_lock(&loaded_mutex); | ||
|  | 			arrput(loaded_files, next); | ||
|  | 			kinc_mutex_unlock(&loaded_mutex); | ||
|  | 
 | ||
|  | 			has_next = false; | ||
|  | 			kinc_mutex_lock(&loading_mutex); | ||
|  | 			if (arrlen(loading_files) > 0) { | ||
|  | 				has_next = true; | ||
|  | 				next = arrpop(loading_files); | ||
|  | 			} | ||
|  | 			else { | ||
|  | 				kinc_event_reset(&event); | ||
|  | 			} | ||
|  | 			kinc_mutex_unlock(&loading_mutex); | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void kha_loader_init(void) { | ||
|  | 	kinc_mutex_init(&loaded_mutex); | ||
|  | 	kinc_mutex_init(&loading_mutex); | ||
|  | 	kinc_event_init(&event, false); | ||
|  | 	kinc_thread_init(&thread, run, NULL); | ||
|  | } | ||
|  | 
 | ||
|  | kha_index_t kha_loader_load_blob(const char *filename) { | ||
|  | 	assert(strlen(filename) <= KHA_MAX_PATH_LENGTH); | ||
|  | 	kha_file_reference_t file; | ||
|  | 	memset(&file, 0, sizeof(file)); | ||
|  | 	file.index = next_index++; | ||
|  | 	strcpy(file.name, filename); | ||
|  | 	file.type = KHA_FILE_TYPE_BLOB; | ||
|  | 
 | ||
|  | 	kinc_mutex_lock(&loading_mutex); | ||
|  | 	arrput(loading_files, file); | ||
|  | 	kinc_event_signal(&event); | ||
|  | 	kinc_mutex_unlock(&loading_mutex); | ||
|  | 
 | ||
|  | 	return file.index; | ||
|  | } | ||
|  | 
 | ||
|  | kha_index_t kha_loader_load_image(const char *filename, bool readable) { | ||
|  | 	assert(strlen(filename) <= KHA_MAX_PATH_LENGTH); | ||
|  | 	kha_file_reference_t file; | ||
|  | 	memset(&file, 0, sizeof(file)); | ||
|  | 	file.index = next_index++; | ||
|  | 	strcpy(file.name, filename); | ||
|  | 	file.type = KHA_FILE_TYPE_IMAGE; | ||
|  | 	file.data.image.readable = readable; | ||
|  | 
 | ||
|  | 	kinc_mutex_lock(&loading_mutex); | ||
|  | 	arrput(loading_files, file); | ||
|  | 	kinc_event_signal(&event); | ||
|  | 	kinc_mutex_unlock(&loading_mutex); | ||
|  | 
 | ||
|  | 	return file.index; | ||
|  | } | ||
|  | 
 | ||
|  | kha_index_t kha_loader_load_sound(const char *filename) { | ||
|  | 	assert(strlen(filename) <= KHA_MAX_PATH_LENGTH); | ||
|  | 	kha_file_reference_t file; | ||
|  | 	memset(&file, 0, sizeof(file)); | ||
|  | 	file.index = next_index++; | ||
|  | 	strcpy(file.name, filename); | ||
|  | 	file.type = KHA_FILE_TYPE_SOUND; | ||
|  | 
 | ||
|  | 	kinc_mutex_lock(&loading_mutex); | ||
|  | 	arrput(loading_files, file); | ||
|  | 	kinc_event_signal(&event); | ||
|  | 	kinc_mutex_unlock(&loading_mutex); | ||
|  | 
 | ||
|  | 	return file.index; | ||
|  | } | ||
|  | 
 | ||
|  | kha_file_reference_t kha_loader_get_file(void) { | ||
|  | 	kinc_mutex_lock(&loaded_mutex); | ||
|  | 	if (arrlen(loaded_files) > 0) { | ||
|  | 		kha_file_reference_t file = arrpop(loaded_files); | ||
|  | 		kinc_mutex_unlock(&loaded_mutex); | ||
|  | 		return file; | ||
|  | 	} | ||
|  | 	else { | ||
|  | 		kinc_mutex_unlock(&loaded_mutex); | ||
|  | 		kha_file_reference_t file; | ||
|  | 		memset(&file, 0, sizeof(file)); | ||
|  | 		return file; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void kha_loader_cleanup_blob(kha_blob_t blob) { | ||
|  | 	free(blob.bytes); | ||
|  | } | ||
|  | 
 | ||
|  | void kha_loader_cleanup_sound(kha_sound_t sound) { | ||
|  | 	// sound.samples is transferred to a Float32Array in LoaderImpl.hx and will go into hxcpp GC
 | ||
|  | 	free(sound.compressed_samples); | ||
|  | } |