static int cmp(const void * pa, const void * pb) { const char * a = ( (const struct replay *) pa ) -> name, * b = ( (const struct replay *) pb ) -> name; return strcmp68(a, b); }
int replay68_get(const char * name, const void ** data, int * csize, int * dsize) { const int max = sizeof(replays)/sizeof(*replays); struct replay s; const struct replay *r; s.name = name; r = bsearch(&s, replays, max, sizeof(*replays), cmp); if (!r) { int i; /* This should not happen unless the replay-rom is not sorted * properly. Anyway it does not cost too much work. */ #ifdef DEBUG const char * prev = ""; for (i=0; i<max; ++i) { assert ( strcmp68(prev, replays[i].name) < 0); prev = replays[i].name; } #endif for (i=0; i<max; ++i) if (!strcmp68(name, replays[i].name)) { r = replays+i; break; } } if (r) { if (data) *data = r->data; if (csize) *csize = r->csize; if (dsize) *dsize = r->dsize; } else msg68_warning("rsc68: can't find built-in replay -- *%s*\n", name); return -!r; }
int url68_local_protocol(const char * protocol) { int i; static const char * local_proto[] = { "", "FILE","LOCAL","NULL" /* , "STDIN", "STDOUT" remove this (not seekable) */ }; const int n_proto = sizeof(local_proto)/sizeof(*local_proto); i = 0; if (protocol) { for (; i<n_proto && strcmp68(protocol, local_proto[i]); ++i) ; } return i < n_proto; }
istream68_t * url68_stream_create(const char * url, int mode) { char protocol[16]; char tmp[512]; const int max = sizeof(tmp)-1; istream68_t * isf = 0; int has_protocol; /* in fact protocol:// length */ has_protocol = parse_protocol(protocol, sizeof(protocol), url); if (has_protocol) { if (!strcmp68(protocol, "PASS")) { /* This is special pass thru protocol. It allows to send any other protocol:// or whatever to the default file handler. On some OS with some libC it may be useful. */ url += has_protocol; /* Skip protocol:// part */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "RSC68")) { isf = rsc68_create_url(url, mode, 0); } else if (!strcmp68(protocol, "SC68")) { /* sc68://author/hw/title/track:loop */ url += has_protocol; /* Skip protocol:// part */ strncpy(tmp, "rsc68://music/",max); strncpy(tmp+14, url, max-14); tmp[max] = 0; msg68(-1,"url is now [%s]\n",tmp); isf = rsc68_create_url(tmp, mode, 0); } else if (!strcmp68(protocol, "FILE") || !strcmp68(protocol, "LOCAL")) { url += has_protocol; /* Skip protocol:// part */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "NULL")) { isf = istream68_null_create(url); } else if (!strcmp68(protocol, "AUDIO")) { url += 5+3; isf = istream68_ao_create(url,mode); } else if (!strcmp68(protocol, "STDIN")) { if (mode != 1) return 0; /* stdin is READ_ONLY */ isf = istream68_fd_create("stdin://",0,1); url = "/dev/stdin"; /* fallback */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "STDOUT")) { if (mode != 2) return 0; /* stdout is WRITE_ONLY */ isf = istream68_fd_create("stdout://",1,2); url = "/dev/stdout"; /* fallback */ has_protocol = 0; /* Allow fallback open */ } else if (!strcmp68(protocol, "STDERR")) { if (mode != 2) return 0; /* stderr is WRITE_ONLY */ isf = istream68_fd_create("stderr://",2,2); url = "/dev/stderr"; /* fallback */ has_protocol = 0; /* Allow fallback open */ } else { /* Try cURL for all unknown protocol */ isf = istream68_curl_create(url,mode); } } /* Fallback open only if no protocol (or explicitly allowed) */ if (!has_protocol) { if (!isf) { /* Default open as FILE */ isf = istream68_file_create(url,mode); } if (!isf) { /* Fallback to file descriptor */ isf = istream68_fd_create(url,-1,mode); } } msg68_debug("url68: create url='%s' %c%c => [%s,'%s']\n", strnevernull68(url), (mode&1) ? 'R' : '.', (mode&2) ? 'W' : '.', strok68(!isf), istream68_filename(isf)); return isf; }
int file68_init(int argc, char **argv) { char tmp[1024]; option68_t * opt; if (init) { const int i = init & 3; const char *message[4] = { "clean","initialized","shutdowning","initializing" }; error68("file68: init error -- *%s*", message[i]); argc = -1; goto out_no_init; } init = 3; /* Options */ option68_init(); /* Zlib */ istream68_z_init(); /* Curl */ istream68_curl_init(); /* Xiph AO */ istream68_ao_init(); /* Init resource */ rsc68_init(); /* Loader */ file68_loader_init(); option68_append(opts,sizeof(opts)/sizeof(*opts)); argc = option68_parse(argc, argv, 1); /* Check for --sc68-no-debug */ opt = option68_get("no-debug", 1); if (opt && opt->val.num) { /* Remove all debug messages whatsoever. */ msg68_set_handler(0); } /* Check for --sc68-asid=off|safe|force */ if (opt = option68_get("asid",1), opt) { if (!strcmp68(opt->val.str,"no")) aSIDify = 0; else if (!strcmp68(opt->val.str,"safe")) aSIDify = 1; else if (!strcmp68(opt->val.str,"force")) aSIDify = 2; else msg68_notice("file68: ignore invalid mode for --sc68-asid -- *%s*\n", opt->val.str); } /* Check for --sc68-debug= */ /* postpone: at this point most debug features have not been created yet. it is pretty much useless to set the mask right now. It will be done after all inits. */ #if 0 opt = option68_get("debug", 1); if (op) { debugmsg68_mask = opt->val.num; } #endif /* Get share path from registry */ opt = option68_get("data", 0); if (opt) { /* Get data path from registry */ if (!option68_isset(opt)) { char * e; const char path[] = "Resources"; e = get_reg_path(registry68_rootkey(REGISTRY68_LMK), "SOFTWARE/sashipa/sc68/Install_Dir", tmp, sizeof(tmp)); if (e && (e+sizeof(path) < tmp+sizeof(tmp))) { memcpy(e, path, sizeof(path)); option68_set(opt,tmp); } } /* Setup new data path */ if (option68_isset(opt)) { rsc68_set_share(opt->val.str); #if 0 /* not needed anynore since option68 properly alloc strings */ if (opt->val.str == tmp) option68_unset(opt); /* Must release tmp ! */ #endif } } /* Get user path */ opt = option68_get("home", 0); if (opt) { /* Get user path from HOME */ if (!option68_isset(opt)) { const char path[] = "/.sc68"; const char * env = mygetenv("HOME"); if(env && strlen(env)+sizeof(path) < sizeof(tmp)) { strncpy(tmp,env,sizeof(tmp)); strcat68(tmp,path,sizeof(tmp)); /* $$$ We should test if this directory actually exists */ option68_set(opt,tmp); } } /* Get user path from registry */ if (!option68_isset(opt)) { char * e; const char path[] = "sc68"; e = get_reg_path(registry68_rootkey(REGISTRY68_CUK), "Volatile Environment/APPDATA", tmp, sizeof(tmp)); if (e && (e+sizeof(path) < tmp+sizeof(tmp))) { memcpy(e, path, sizeof(path)); option68_set(opt,tmp); } } /* Setup new user path */ if (option68_isset(opt)) { rsc68_set_user(opt->val.str); if (opt->val.str == tmp) option68_unset(opt); /* Must release tmp ! */ } } /* Setup new music path */ opt = option68_get("music", 1); if (opt) { rsc68_set_music(opt->val.str); } /* Setup new remote path */ opt = option68_get("remote", 1); if (opt) { rsc68_set_remote_music(opt->val.str); } init = 1; out_no_init: return argc; }