X-Git-Url: https://develop.uap-core.de/gitweb/uwplayer.git/blobdiff_plain/a5bc5f23f204464e636227b79759d46a97df3a0e..HEAD:/application/settings.c?ds=sidebyside diff --git a/application/settings.c b/application/settings.c index aa1b976..ac45d5d 100644 --- a/application/settings.c +++ b/application/settings.c @@ -31,14 +31,22 @@ #include #include +#include +#include + + #include "main.h" #include "utils.h" #include "json.h" +#include "window.h" +#include "playlist.h" -#include -#include -#include -#include +#include +#include +//include +#include +#include +#include #define CONFIG_BASE_DIR ".config" #define UWP_CONFIG_DIR "uwplayer" @@ -51,6 +59,8 @@ static void conf_load_global_settings(void); static char *uwp_config_dir; +static int instance_socket = -1; + /* * root json config object */ @@ -59,12 +69,12 @@ static JSONObject *uwp_config; /* * global settings from json config converted to key/value pairs */ -static UcxMap *uwp_settings; +static CxMap *uwp_settings; /* * default settings */ -static UcxMap *uwp_default; +static CxMap *uwp_default; static int check_config_dir(void) { char *home = getenv("HOME"); @@ -100,8 +110,8 @@ int load_config(void) { return 1; } - uwp_settings = ucx_map_new(16); - uwp_default = ucx_map_new(32); + uwp_settings = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16); + uwp_default = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 32); char *cfgfile_path = util_concat_path(uwp_config_dir, UWP_CONFIG_FILE); FILE *cfgfile = fopen(cfgfile_path, "r"); @@ -151,8 +161,8 @@ int load_config(void) { // check if mpv or mplayer binaries are configured - char *player_bin = ucx_map_cstr_get(uwp_settings, UWP_PLAYER_BIN); - char *player_type = ucx_map_cstr_get(uwp_settings, UWP_PLAYER_TYPE); + char *player_bin = cxMapGet(uwp_settings, cx_hash_key_str(UWP_PLAYER_BIN)); + char *player_type = cxMapGet(uwp_settings, cx_hash_key_str(UWP_PLAYER_TYPE)); if(!player_bin) { // try to find the mpv or mplayer binary path @@ -181,17 +191,17 @@ static void conf_load_global_settings(void) { for(size_t i=0;isize;i++) { JSONObjValue *gs = &s->values[i]; if(gs->value->type == JSON_STRING) { - ucx_map_cstr_put(uwp_settings, gs->name, gs->value->value.string.string); + cxMapPut(uwp_settings, cx_hash_key_str(gs->name), strdup(gs->value->value.string.string)); } } } -static char* get_which_output(FILE *f, UcxBuffer *buf) { +static char* get_which_output(FILE *f, CxBuffer *buf) { buf->pos = 0; buf->size = 0; - ucx_stream_copy(f, buf, (read_func)fread, (write_func)ucx_buffer_write); + cx_stream_copy(f, buf, (cx_read_func)fread, (cx_write_func)cxBufferWrite); if(!pclose(f)) { - ucx_buffer_putc(buf, 0); + cxBufferPut(buf, 0); size_t i; for(i=0;ipos;i++) { if(buf->space[i] == '\n') { @@ -206,32 +216,33 @@ static char* get_which_output(FILE *f, UcxBuffer *buf) { static Boolean finish_bin_search(XtPointer data) { PlayerInfo *playerInfo = data; - ucx_map_cstr_put(uwp_settings, UWP_PLAYER_BIN, playerInfo->bin); - ucx_map_cstr_put(uwp_settings, UWP_PLAYER_TYPE, playerInfo->type); + cxMapPut(uwp_settings, cx_hash_key_str(UWP_PLAYER_BIN), playerInfo->bin); + cxMapPut(uwp_settings, cx_hash_key_str(UWP_PLAYER_TYPE), playerInfo->type); free(playerInfo); return 0; } static void* player_bin_search_thread(void *data) { - UcxBuffer *buf = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); + CxBuffer buf; + cxBufferInit(&buf, NULL, 256, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); FILE *f = popen("which mpv", "r"); if(f) { - char *bin = get_which_output(f, buf); + char *bin = get_which_output(f, &buf); if(bin) { PlayerInfo *playerInfo = malloc(sizeof(PlayerInfo)); playerInfo->bin = strdup(bin); playerInfo->type = strdup("mpv"); AppExecProc(finish_bin_search, playerInfo); - ucx_buffer_free(buf); + cxBufferDestroy(&buf); return NULL; } } f = popen("which mplayer", "r"); if(f) { - char *bin = get_which_output(f, buf); + char *bin = get_which_output(f, &buf); if(bin) { PlayerInfo *playerInfo = malloc(sizeof(PlayerInfo)); playerInfo->bin = strdup(bin); @@ -240,10 +251,188 @@ static void* player_bin_search_thread(void *data) { } } - ucx_buffer_free(buf); + cxBufferDestroy(&buf); return NULL; } char* SettingsGetPlayerBin(void) { - return ucx_map_cstr_get(uwp_settings, UWP_PLAYER_BIN); + return cxMapGet(uwp_settings, cx_hash_key_str(UWP_PLAYER_BIN)); +} + + +char *InstanceFilePath(Display *dp) { + cxmutstr instance_file = cx_asprintf("instance%s", DisplayString(dp)); + char *path = util_concat_path(uwp_config_dir, instance_file.ptr); + free(instance_file.ptr); + return path; +} + +int ConnectToInstance(const char *path) { + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(!fd) { + return -1; + } + + size_t path_len = strlen(path); + + struct sockaddr_un addr; + if(path_len > sizeof(addr.sun_path)-1) { + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, path, strlen(path) + 1); + + if(connect(fd, (struct sockaddr*)&addr, sizeof(addr))) { + close(fd); + return -1; + } + + return fd; +} + +int CreateSingleInstanceSocket(Display *dp, Bool *already_running) { + char *instance_path = InstanceFilePath(dp); + size_t instance_path_len = strlen(instance_path); + *already_running = 0; + + // check path + struct sockaddr_un addr; + if(instance_path_len > sizeof(addr.sun_path)-1) { + fprintf(stderr, "instance path '%s' too long for unix domain socket", instance_path); + free(instance_path); + return 1; + } + + // check if the socket already exists and is open + struct stat s; + if(!stat(instance_path, &s)) { + int fd = ConnectToInstance(instance_path); + close(fd); + if(fd >= 0) { + *already_running = 1; + return 0; // instance already running + } + + // instance not running but socket file exists + // remove socket before creating a new socket + unlink(instance_path); + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, instance_path, instance_path_len+1); + + free(instance_path); + instance_socket = socket(AF_UNIX, SOCK_STREAM, 0); + if(instance_socket < 0) { + fprintf(stderr, "cannot create instance socket: %s", strerror(errno)); + return 1; + } + + if(bind(instance_socket, (struct sockaddr*)&addr, sizeof(addr))) { + fprintf(stderr, "cannot bind instance socket: %s", strerror(errno)); + return 1; + } + + pthread_t tid; + if(pthread_create(&tid, NULL, instance_socket_thread, NULL)) { + close(instance_socket); + instance_socket = -1; + return -1; + } + pthread_detach(tid); + + return 0; +} + +static Boolean cmd_open(XtPointer data) { + MainWindow *win = GetMainWindow(); + char *file = data; + printf("open %s\n", file); + + PlayListClear(win); + PlayListAddFile(win, file); + PlayListPlayTrack(win, win->playlist.tracks->size-1); + + free(data); + return 0; +} + +static void process_msg(CxBuffer *msgbuf, size_t *rpos) { + cxstring msg = cx_strn(NULL, 0); + for(size_t i=*rpos;isize;i++) { + if(msgbuf->space[i] == '\n') { + msg.ptr = msgbuf->space + *rpos; + msg.length = i - *rpos; + *rpos = i+1; + break; + } + } + + if(msg.length > 0) { + if(cx_strprefix(msg, CX_STR("open "))) { + cxstring file = cx_strsubs(msg, 5); + cxmutstr mfile = cx_strdup(file); + AppExecProc(cmd_open, mfile.ptr); + } else { + fprintf(stderr, "unknown instance command: {%.*s}\n", (int)msg.length, msg.ptr); + } + + if(*rpos < msgbuf->size) { + process_msg(msgbuf, rpos); + } + } +} + +void* instance_socket_thread(void *data) { + listen(instance_socket, 8); + + CxBuffer msgbuf; + cxBufferInit(&msgbuf, NULL, 1024, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + + char buf[1024]; + + while(TRUE) { + printf("accept instance socket\n"); + int fd = accept(instance_socket, NULL, 0); + if(fd < 0) { + break; + } + printf("accept instance connection\n"); + + msgbuf.pos = 0; + msgbuf.size = 0; + size_t rpos = 0; + + ssize_t r; + while((r = read(fd, buf, 1024)) > 0) { + cxBufferWrite(buf, 1, r, &msgbuf); + process_msg(&msgbuf, &rpos); + } + + printf("close instance connection\n"); + close(fd); + } + + cxBufferDestroy(&msgbuf); + + printf("instance socket shutdown\n"); + + return NULL; +} + +void ShutdownInstanceSocket(Display *dp) { + if(instance_socket < 0) { + return; + } + + shutdown(instance_socket, SHUT_RDWR); + close(instance_socket); + instance_socket = -1; + + char *instance_path = InstanceFilePath(dp); + unlink(instance_path); + free(instance_path); }