2 * Copyright 2022 Olaf Wintermann
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
39 #include <cx/hash_map.h>
40 //include <ucx/properties.h>
41 #include <cx/buffer.h>
44 #define CONFIG_BASE_DIR ".config"
45 #define UWP_CONFIG_DIR "uwplayer"
46 #define UWP_CONFIG_FILE "uwplayer.conf"
48 #define JS_READ_BUFSIZE 4096
50 static void* player_bin_search_thread(void *data);
51 static void conf_load_global_settings(void);
53 static char *uwp_config_dir;
56 * root json config object
58 static JSONObject *uwp_config;
61 * global settings from json config converted to key/value pairs
63 static CxMap *uwp_settings;
68 static CxMap *uwp_default;
70 static int check_config_dir(void) {
71 char *home = getenv("HOME");
76 char *cfg_dir = util_concat_path(home, CONFIG_BASE_DIR);
78 if(mkdir(cfg_dir, S_IRWXU)) {
80 fprintf(stderr, "Error: Cannot access %s: %s\n", cfg_dir, strerror(errno));
86 uwp_config_dir = util_concat_path(cfg_dir, UWP_CONFIG_DIR);
87 if(mkdir(uwp_config_dir, S_IRWXU)) {
89 fprintf(stderr, "Error: Cannot access %s: %s\n", uwp_config_dir, strerror(errno));
99 int load_config(void) {
100 if(check_config_dir()) {
104 uwp_settings = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16);
105 uwp_default = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 32);
107 char *cfgfile_path = util_concat_path(uwp_config_dir, UWP_CONFIG_FILE);
108 FILE *cfgfile = fopen(cfgfile_path, "r");
113 JSONParser *parser = json_parser_new();
115 JSONValue *value = NULL;
116 char buf[JS_READ_BUFSIZE];
119 while((ret = json_read_value(parser, &value)) >= 0) {
121 r = fread(buf, 1, JS_READ_BUFSIZE, cfgfile);
125 json_parser_fill(parser, buf, r);
131 json_parser_free(parser);
134 if(value->type == JSON_OBJECT) {
136 uwp_config = &value->value.object;
137 conf_load_global_settings();
154 // check if mpv or mplayer binaries are configured
155 char *player_bin = cxMapGet(uwp_settings, cx_hash_key_str(UWP_PLAYER_BIN));
156 char *player_type = cxMapGet(uwp_settings, cx_hash_key_str(UWP_PLAYER_TYPE));
159 // try to find the mpv or mplayer binary path
161 pthread_create(&st, NULL, player_bin_search_thread, NULL);
162 } else if(!player_type) {
163 fprintf(stderr, "Warning: unknown player type (mplayer, mpv)\n");
169 static void conf_load_global_settings(void) {
170 JSONValue *settings = json_obj_get(uwp_config, "settings");
175 if(settings->type != JSON_OBJECT) {
176 fprintf(stderr, "Warning: 'settings' not an object\n");
180 JSONObject *s = &settings->value.object;
182 for(size_t i=0;i<s->size;i++) {
183 JSONObjValue *gs = &s->values[i];
184 if(gs->value->type == JSON_STRING) {
185 cxMapPut(uwp_settings, cx_hash_key_str(gs->name), strdup(gs->value->value.string.string));
190 static char* get_which_output(FILE *f, CxBuffer *buf) {
193 cx_stream_copy(f, buf, (cx_read_func)fread, (cx_write_func)cxBufferWrite);
197 for(i=0;i<buf->pos;i++) {
198 if(buf->space[i] == '\n') {
208 static Boolean finish_bin_search(XtPointer data) {
209 PlayerInfo *playerInfo = data;
210 cxMapPut(uwp_settings, cx_hash_key_str(UWP_PLAYER_BIN), playerInfo->bin);
211 cxMapPut(uwp_settings, cx_hash_key_str(UWP_PLAYER_TYPE), playerInfo->type);
216 static void* player_bin_search_thread(void *data) {
218 cxBufferInit(&buf, NULL, 256, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
220 FILE *f = popen("which mpv", "r");
222 char *bin = get_which_output(f, &buf);
224 PlayerInfo *playerInfo = malloc(sizeof(PlayerInfo));
225 playerInfo->bin = strdup(bin);
226 playerInfo->type = strdup("mpv");
227 AppExecProc(finish_bin_search, playerInfo);
229 cxBufferDestroy(&buf);
234 f = popen("which mplayer", "r");
236 char *bin = get_which_output(f, &buf);
238 PlayerInfo *playerInfo = malloc(sizeof(PlayerInfo));
239 playerInfo->bin = strdup(bin);
240 playerInfo->type = strdup("mplayer");
241 AppExecProc(finish_bin_search, playerInfo);
245 cxBufferDestroy(&buf);
249 char* SettingsGetPlayerBin(void) {
250 return cxMapGet(uwp_settings, cx_hash_key_str(UWP_PLAYER_BIN));