diff options
Diffstat (limited to 'apps/open_plugin.c')
-rw-r--r-- | apps/open_plugin.c | 282 |
1 files changed, 201 insertions, 81 deletions
diff --git a/apps/open_plugin.c b/apps/open_plugin.c index 7b5513a92b..32b5195334 100644 --- a/apps/open_plugin.c +++ b/apps/open_plugin.c | |||
@@ -27,6 +27,10 @@ | |||
27 | #include "splash.h" | 27 | #include "splash.h" |
28 | #include "lang.h" | 28 | #include "lang.h" |
29 | 29 | ||
30 | /* Define LOGF_ENABLE to enable logf output in this file */ | ||
31 | //#define LOGF_ENABLE | ||
32 | #include "logf.h" | ||
33 | |||
30 | #define ROCK_EXT "rock" | 34 | #define ROCK_EXT "rock" |
31 | #define ROCK_LEN 5 | 35 | #define ROCK_LEN 5 |
32 | #define OP_EXT "opx" | 36 | #define OP_EXT "opx" |
@@ -40,47 +44,132 @@ static int open_plugin_hash_get_entry(uint32_t hash, | |||
40 | struct open_plugin_entry_t *entry, | 44 | struct open_plugin_entry_t *entry, |
41 | const char* dat_file); | 45 | const char* dat_file); |
42 | 46 | ||
47 | static const char* strip_rockbox_root(const char *path) | ||
48 | { | ||
49 | int dlen = strlen(ROCKBOX_DIR); | ||
50 | if (strncmp(path, ROCKBOX_DIR, dlen) == 0) | ||
51 | path+= dlen; | ||
52 | return path; | ||
53 | } | ||
54 | |||
43 | static inline void op_clear_entry(struct open_plugin_entry_t *entry) | 55 | static inline void op_clear_entry(struct open_plugin_entry_t *entry) |
44 | { | 56 | { |
45 | if (entry) | 57 | if (entry == NULL) |
58 | return; | ||
59 | memset(entry, 0, op_entry_sz); | ||
60 | entry->lang_id = -1; | ||
61 | } | ||
62 | |||
63 | static int op_find_entry(int fd, struct open_plugin_entry_t *entry, | ||
64 | uint32_t hash, int32_t lang_id) | ||
65 | { | ||
66 | int ret = OPEN_PLUGIN_NOT_FOUND; | ||
67 | int record = -1; | ||
68 | if (fd >= 0 && entry != NULL) | ||
46 | { | 69 | { |
47 | memset(entry, 0, op_entry_sz); | 70 | logf("OP find_entry *Searching* hash: %x lang_id: %d", hash, lang_id); |
48 | entry->lang_id = -1; | 71 | while (read(fd, entry, op_entry_sz) == op_entry_sz) |
72 | { | ||
73 | record++; | ||
74 | if (entry->lang_id == lang_id || | ||
75 | (entry->hash == hash && hash != 0) || | ||
76 | (lang_id == OPEN_PLUGIN_LANG_IGNOREALL))/* return first entry found */ | ||
77 | { | ||
78 | /* NULL terminate fields NOTE -- all are actually +1 larger */ | ||
79 | entry->name[OPEN_PLUGIN_NAMESZ] = '\0'; | ||
80 | /*entry->key[OPEN_PLUGIN_BUFSZ] = '\0';*/ | ||
81 | entry->path[OPEN_PLUGIN_BUFSZ] = '\0'; | ||
82 | entry->param[OPEN_PLUGIN_BUFSZ] = '\0'; | ||
83 | ret = record; | ||
84 | logf("OP find_entry *Found* hash: %x lang_id: %d", | ||
85 | entry->hash, entry->lang_id); | ||
86 | logf("OP find_entry rec: %d name: %s %s %s", record, | ||
87 | entry->name, entry->path, entry->param); | ||
88 | break; | ||
89 | } | ||
90 | } | ||
49 | } | 91 | } |
92 | return ret; | ||
50 | } | 93 | } |
51 | 94 | ||
52 | static int op_update_dat(struct open_plugin_entry_t *entry, bool clear) | 95 | static int op_update_dat(struct open_plugin_entry_t *entry, bool clear) |
53 | { | 96 | { |
54 | int fd, fd1; | 97 | int fd; |
55 | uint32_t hash; | 98 | uint32_t hash; |
56 | 99 | int32_t lang_id; | |
57 | if (!entry || entry->hash == 0) | 100 | if (!entry || entry->hash == 0) |
58 | return -1; | 101 | { |
102 | logf("OP update *No entry*"); | ||
103 | return OPEN_PLUGIN_NOT_FOUND; | ||
104 | } | ||
59 | 105 | ||
60 | hash = entry->hash; | 106 | hash = entry->hash; |
107 | lang_id = entry->lang_id; | ||
108 | if (lang_id <= OPEN_PLUGIN_LANG_INVALID) | ||
109 | lang_id = OPEN_PLUGIN_LANG_IGNORE; | ||
110 | |||
111 | logf("OP update hash: %x lang_id: %d", hash, lang_id); | ||
112 | logf("OP update name: %s clear: %d", entry->name, (int) clear); | ||
113 | logf("OP update %s %s %s", entry->name, entry->path, entry->param); | ||
114 | #if (CONFIG_STORAGE & STORAGE_ATA) /* Harddrive -- update existing */ | ||
115 | logf("OP update *Updating entries* %s", OPEN_PLUGIN_DAT); | ||
116 | fd = open(OPEN_PLUGIN_DAT, O_RDWR | O_CREAT, 0666); | ||
61 | 117 | ||
62 | fd = open(OPEN_PLUGIN_DAT ".tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666); | ||
63 | if (fd < 0) | 118 | if (fd < 0) |
64 | return -1; | 119 | return OPEN_PLUGIN_NOT_FOUND; |
120 | /* Only read the hash and lang id */ | ||
121 | uint32_t hash_langid[2] = {0}; | ||
122 | while (read(fd, &hash_langid, sizeof(hash_langid)) == sizeof(hash_langid)) | ||
123 | { | ||
124 | if (hash_langid[0] == hash || (int32_t)hash_langid[1] == lang_id) | ||
125 | { | ||
126 | logf("OP update *Entry Exists* hash: %x langid: %d", | ||
127 | hash_langid[0], (int32_t)hash_langid[1]); | ||
128 | lseek(fd, 0-sizeof(hash_langid), SEEK_CUR);/* back to the start of record */ | ||
129 | break; | ||
130 | } | ||
131 | lseek(fd, op_entry_sz - sizeof(hash_langid), SEEK_CUR); /* finish record */ | ||
132 | } | ||
65 | write(fd, entry, op_entry_sz); | 133 | write(fd, entry, op_entry_sz); |
134 | close(fd); | ||
135 | #else /* Everyone else make a temp file */ | ||
136 | logf("OP update *Copying entries* %s", OPEN_PLUGIN_DAT ".tmp"); | ||
137 | fd = open(OPEN_PLUGIN_DAT ".tmp", O_RDWR | O_CREAT | O_TRUNC, 0666); | ||
66 | 138 | ||
67 | fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY); | 139 | if (fd < 0) |
140 | return OPEN_PLUGIN_NOT_FOUND; | ||
141 | write(fd, entry, op_entry_sz); | ||
142 | |||
143 | int fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY); | ||
68 | if (fd1 >= 0) | 144 | if (fd1 >= 0) |
69 | { | 145 | { |
70 | while (read(fd1, &open_plugin_entry, op_entry_sz) == op_entry_sz) | 146 | /* copy non-duplicate entries back from original */ |
147 | while (read(fd1, entry, op_entry_sz) == op_entry_sz) | ||
71 | { | 148 | { |
72 | if (open_plugin_entry.hash != hash) | 149 | if (entry->hash != hash && entry->lang_id != lang_id) |
73 | write(fd, &open_plugin_entry, op_entry_sz); | 150 | { |
151 | write(fd, entry, op_entry_sz); | ||
152 | } | ||
74 | } | 153 | } |
75 | close(fd1); | 154 | close(fd1); |
76 | remove(OPEN_PLUGIN_DAT); | 155 | remove(OPEN_PLUGIN_DAT); |
77 | } | 156 | } |
157 | if (!clear) /* retrieve original entry */ | ||
158 | { | ||
159 | logf("OP update *Loading original entry*"); | ||
160 | lseek(fd, 0, SEEK_SET); | ||
161 | int opret = op_find_entry(fd, entry, hash, lang_id); | ||
162 | clear = (opret == OPEN_PLUGIN_NOT_FOUND); | ||
163 | } | ||
78 | close(fd); | 164 | close(fd); |
79 | |||
80 | rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT); | 165 | rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT); |
166 | #endif | ||
81 | 167 | ||
82 | if (clear) | 168 | if (clear) |
83 | op_clear_entry(&open_plugin_entry); | 169 | { |
170 | logf("OP update *Clearing entry*"); | ||
171 | op_clear_entry(entry); | ||
172 | } | ||
84 | 173 | ||
85 | return 0; | 174 | return 0; |
86 | } | 175 | } |
@@ -88,31 +177,33 @@ static int op_update_dat(struct open_plugin_entry_t *entry, bool clear) | |||
88 | uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter) | 177 | uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter) |
89 | { | 178 | { |
90 | int len; | 179 | int len; |
91 | bool is_valid = false; | ||
92 | uint32_t hash; | 180 | uint32_t hash; |
93 | int32_t lang_id; | 181 | int32_t lang_id; |
94 | char *pos = "\0"; | 182 | char *pos = "\0"; |
95 | 183 | ||
96 | if(!key) | 184 | if(!key) |
97 | { | 185 | { |
186 | logf("OP add_path No Key, *Clearing entry*"); | ||
98 | op_clear_entry(&open_plugin_entry); | 187 | op_clear_entry(&open_plugin_entry); |
99 | return 0; | 188 | return 0; |
100 | } | 189 | } |
101 | 190 | ||
102 | lang_id = P2ID((unsigned char*)key); | 191 | lang_id = P2ID((unsigned char*)key); |
103 | key = P2STR((unsigned char *)key); | 192 | const char *skey = P2STR((unsigned char *)key); |
104 | 193 | logf("OP add_path key: %s lang id: %d", skey, lang_id); | |
105 | open_plugin_get_hash(key, &hash); | 194 | open_plugin_get_hash(strip_rockbox_root(skey), &hash); |
106 | |||
107 | 195 | ||
108 | if(open_plugin_entry.hash != hash) | 196 | if(open_plugin_entry.hash != hash) |
109 | { | 197 | { |
198 | logf("OP add_path *Flush entry*"); | ||
110 | /* the entry in ram needs saved */ | 199 | /* the entry in ram needs saved */ |
111 | op_update_dat(&open_plugin_entry, true); | 200 | op_update_dat(&open_plugin_entry, true); |
112 | } | 201 | } |
113 | 202 | ||
114 | if (plugin) | 203 | if (plugin) |
115 | { | 204 | { |
205 | open_plugin_entry.hash = hash; | ||
206 | open_plugin_entry.lang_id = lang_id; | ||
116 | /* name */ | 207 | /* name */ |
117 | if (path_basename(plugin, (const char **)&pos) == 0) | 208 | if (path_basename(plugin, (const char **)&pos) == 0) |
118 | pos = "\0"; | 209 | pos = "\0"; |
@@ -120,45 +211,46 @@ uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *p | |||
120 | len = strlcpy(open_plugin_entry.name, pos, OPEN_PLUGIN_NAMESZ); | 211 | len = strlcpy(open_plugin_entry.name, pos, OPEN_PLUGIN_NAMESZ); |
121 | if (len > ROCK_LEN && strcasecmp(&(pos[len-ROCK_LEN]), "." ROCK_EXT) == 0) | 212 | if (len > ROCK_LEN && strcasecmp(&(pos[len-ROCK_LEN]), "." ROCK_EXT) == 0) |
122 | { | 213 | { |
123 | is_valid = true; | ||
124 | |||
125 | /* path */ | 214 | /* path */ |
126 | strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ); | 215 | strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ); |
127 | 216 | ||
128 | if(parameter) | 217 | if(!parameter) |
129 | strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ); | 218 | parameter = ""; |
130 | else | 219 | strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ); |
131 | open_plugin_entry.param[0] = '\0'; | 220 | goto retnhash; |
132 | } | 221 | } |
133 | else if (len > OP_LEN && strcasecmp(&(pos[len-OP_LEN]), "." OP_EXT) == 0) | 222 | else if (len > OP_LEN && strcasecmp(&(pos[len-OP_LEN]), "." OP_EXT) == 0) |
134 | { | 223 | { |
135 | is_valid = true; | ||
136 | open_plugin_hash_get_entry(0, &open_plugin_entry, plugin); | 224 | open_plugin_hash_get_entry(0, &open_plugin_entry, plugin); |
225 | goto retnhash; | ||
137 | } | 226 | } |
138 | } | 227 | } |
139 | 228 | ||
140 | if (!is_valid) | 229 | logf("OP add_path Invalid, *Clearing entry*"); |
141 | { | 230 | if (lang_id != LANG_SHORTCUTS) /* from shortcuts menu */ |
142 | if (lang_id != LANG_SHORTCUTS) /* from shortcuts menu */ | 231 | splashf(HZ * 2, str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos); |
143 | splashf(HZ / 2, str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos); | 232 | op_clear_entry(&open_plugin_entry); |
144 | op_clear_entry(&open_plugin_entry); | 233 | hash = 0; |
145 | hash = 0; | 234 | |
146 | } | 235 | retnhash: |
147 | else | 236 | logf("OP add_path name: %s %s %s", |
148 | { | 237 | open_plugin_entry.name, |
149 | open_plugin_entry.hash = hash; | 238 | open_plugin_entry.path, |
150 | open_plugin_entry.lang_id = lang_id; | 239 | open_plugin_entry.param); |
151 | } | ||
152 | |||
153 | return hash; | 240 | return hash; |
154 | } | 241 | } |
155 | 242 | ||
156 | void open_plugin_browse(const char *key) | 243 | void open_plugin_browse(const char *key) |
157 | { | 244 | { |
245 | logf("OP Browse"); | ||
158 | struct browse_context browse; | 246 | struct browse_context browse; |
159 | char tmp_buf[OPEN_PLUGIN_BUFSZ+1]; | 247 | char tmp_buf[OPEN_PLUGIN_BUFSZ+1]; |
160 | open_plugin_get_entry(key, &open_plugin_entry); | 248 | open_plugin_get_entry(key, &open_plugin_entry); |
161 | 249 | ||
250 | logf("OP browse key: %s name: %s", | ||
251 | (key ? P2STR((unsigned char *)key):"No Key") ,open_plugin_entry.name); | ||
252 | logf("OP browse %s %s", open_plugin_entry.path, open_plugin_entry.param); | ||
253 | |||
162 | if (open_plugin_entry.path[0] == '\0') | 254 | if (open_plugin_entry.path[0] == '\0') |
163 | strcpy(open_plugin_entry.path, PLUGIN_DIR"/"); | 255 | strcpy(open_plugin_entry.path, PLUGIN_DIR"/"); |
164 | 256 | ||
@@ -172,78 +264,105 @@ void open_plugin_browse(const char *key) | |||
172 | open_plugin_add_path(key, tmp_buf, NULL); | 264 | open_plugin_add_path(key, tmp_buf, NULL); |
173 | } | 265 | } |
174 | 266 | ||
175 | static int open_plugin_hash_get_entry(uint32_t hash, | 267 | static int op_get_entry(uint32_t hash, int32_t lang_id, |
176 | struct open_plugin_entry_t *entry, | 268 | struct open_plugin_entry_t *entry, const char *dat_file) |
177 | const char* dat_file) | ||
178 | { | 269 | { |
179 | int ret = -1, record = -1; | 270 | int opret = OPEN_PLUGIN_NOT_FOUND; |
180 | 271 | ||
181 | if (entry) | 272 | if (entry) |
182 | { | 273 | { |
274 | /* Is the entry we want already loaded? */ | ||
275 | if(hash != 0 && entry->hash == hash) | ||
276 | return OPEN_PLUGIN_NEEDS_FLUSHED; | ||
183 | 277 | ||
184 | if (hash != 0) | 278 | if(lang_id <= OPEN_PLUGIN_LANG_INVALID) |
185 | { | 279 | { |
186 | if(entry->hash == hash) /* hasn't been flushed yet? */ | 280 | lang_id = OPEN_PLUGIN_LANG_IGNORE; |
187 | return -2; | 281 | if (hash == 0)/* no hash or langid -- returns first entry found */ |
188 | else | 282 | lang_id = OPEN_PLUGIN_LANG_IGNOREALL; |
189 | op_update_dat(&open_plugin_entry, true); | ||
190 | } | 283 | } |
284 | else if(entry->lang_id == lang_id) | ||
285 | { | ||
286 | return OPEN_PLUGIN_NEEDS_FLUSHED; | ||
287 | } | ||
288 | |||
289 | /* if another entry is loaded; flush it to disk before we destroy it */ | ||
290 | op_update_dat(&open_plugin_entry, true); | ||
291 | |||
292 | logf("OP get_entry hash: %x lang id: %d db: %s", hash, lang_id, dat_file); | ||
191 | 293 | ||
192 | int fd = open(dat_file, O_RDONLY); | 294 | int fd = open(dat_file, O_RDONLY); |
295 | opret = op_find_entry(fd, entry, hash, lang_id); | ||
296 | close(fd); | ||
193 | 297 | ||
194 | if (fd >= 0) | 298 | if (opret < 0) /* nothing found */ |
195 | { | 299 | { |
196 | while (read(fd, entry, op_entry_sz) == op_entry_sz) | 300 | op_clear_entry(entry); |
197 | { | ||
198 | record++; | ||
199 | if (hash == 0 || entry->hash == hash) | ||
200 | { | ||
201 | /* NULL terminate fields NOTE -- all are actually +1 larger */ | ||
202 | entry->name[OPEN_PLUGIN_NAMESZ] = '\0'; | ||
203 | /*entry->key[OPEN_PLUGIN_BUFSZ] = '\0';*/ | ||
204 | entry->path[OPEN_PLUGIN_BUFSZ] = '\0'; | ||
205 | entry->param[OPEN_PLUGIN_BUFSZ] = '\0'; | ||
206 | ret = record; | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | close(fd); | ||
211 | } | ||
212 | if (ret < 0) | ||
213 | { | ||
214 | memset(entry, 0, op_entry_sz); | ||
215 | entry->lang_id = -1; | ||
216 | } | 301 | } |
217 | } | 302 | } |
218 | 303 | ||
219 | return ret; | 304 | return opret; |
305 | } | ||
306 | |||
307 | #if 0 //unused | ||
308 | static int open_plugin_langid_get_entry(int32_t lang_id, | ||
309 | struct open_plugin_entry_t *entry, | ||
310 | const char *dat_file) | ||
311 | { | ||
312 | return op_get_entry(0, lang_id, entry, dat_file); | ||
313 | } | ||
314 | #endif | ||
315 | |||
316 | static int open_plugin_hash_get_entry(uint32_t hash, | ||
317 | struct open_plugin_entry_t *entry, | ||
318 | const char *dat_file) | ||
319 | { | ||
320 | return op_get_entry(hash, OPEN_PLUGIN_LANG_IGNORE, entry, dat_file); | ||
220 | } | 321 | } |
221 | 322 | ||
222 | int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry) | 323 | int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry) |
223 | { | 324 | { |
325 | if (!key || !entry) | ||
326 | return OPEN_PLUGIN_NOT_FOUND; | ||
327 | int opret; | ||
224 | uint32_t hash; | 328 | uint32_t hash; |
225 | key = P2STR((unsigned char *)key); | 329 | int32_t lang_id = P2ID((unsigned char *)key); |
330 | const char* skey = P2STR((unsigned char *)key); /* string|LANGPTR => string */ | ||
331 | |||
332 | open_plugin_get_hash(strip_rockbox_root(skey), &hash); /* in open_plugin.h */ | ||
333 | |||
334 | opret = op_get_entry(hash, lang_id, entry, OPEN_PLUGIN_DAT); | ||
335 | logf("OP entry hash: %x lang id: %d ret: %d key: %s", hash, lang_id, opret, skey); | ||
226 | 336 | ||
227 | open_plugin_get_hash(key, &hash); /* in open_plugin.h */ | 337 | if (opret == OPEN_PLUGIN_NOT_FOUND && lang_id > OPEN_PLUGIN_LANG_INVALID) |
228 | return open_plugin_hash_get_entry(hash, entry, OPEN_PLUGIN_DAT); | 338 | { /* try rb defaults */ |
339 | opret = op_get_entry(hash, lang_id, entry, OPEN_RBPLUGIN_DAT); | ||
340 | logf("OP rb_entry hash: %x lang id: %d ret: %d key: %s", hash, lang_id, opret, skey); | ||
341 | /* add to the user plugin.dat file if found */ | ||
342 | op_update_dat(entry, false); | ||
343 | |||
344 | } | ||
345 | logf("OP entry ret: %s", (opret == OPEN_PLUGIN_NOT_FOUND ? "Not Found":"Found")); | ||
346 | return opret; | ||
229 | } | 347 | } |
230 | 348 | ||
231 | int open_plugin_run(const char *key) | 349 | int open_plugin_run(const char *key) |
232 | { | 350 | { |
233 | int ret = 0; | 351 | int ret = 0; |
234 | const char *path; | 352 | int opret = open_plugin_get_entry(key, &open_plugin_entry); |
235 | const char *param; | 353 | if (opret == OPEN_PLUGIN_NEEDS_FLUSHED) |
236 | |||
237 | if (open_plugin_get_entry(key, &open_plugin_entry) == -2) /* entry needs flushed */ | ||
238 | op_update_dat(&open_plugin_entry, false); | 354 | op_update_dat(&open_plugin_entry, false); |
355 | const char *path = open_plugin_entry.path; | ||
356 | const char *param = open_plugin_entry.param; | ||
357 | |||
358 | logf("OP run key: %s ret: %d name: %s", | ||
359 | (key ? P2STR((unsigned char *)key):"No Key"), opret, open_plugin_entry.name); | ||
360 | logf("OP run: %s %s %s", open_plugin_entry.name, path, param); | ||
239 | 361 | ||
240 | path = open_plugin_entry.path; | ||
241 | param = open_plugin_entry.param; | ||
242 | if (param[0] == '\0') | 362 | if (param[0] == '\0') |
243 | param = NULL; | 363 | param = NULL; |
244 | 364 | ||
245 | if (path) | 365 | ret = plugin_load(path, param); |
246 | ret = plugin_load(path, param); | ||
247 | 366 | ||
248 | if (ret != GO_TO_PLUGIN) | 367 | if (ret != GO_TO_PLUGIN) |
249 | op_clear_entry(&open_plugin_entry); | 368 | op_clear_entry(&open_plugin_entry); |
@@ -253,6 +372,7 @@ int open_plugin_run(const char *key) | |||
253 | 372 | ||
254 | void open_plugin_cache_flush(void) | 373 | void open_plugin_cache_flush(void) |
255 | { | 374 | { |
375 | logf("OP *cache flush*"); | ||
256 | op_update_dat(&open_plugin_entry, true); | 376 | op_update_dat(&open_plugin_entry, true); |
257 | } | 377 | } |
258 | 378 | ||