summaryrefslogtreecommitdiff
path: root/apps/open_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/open_plugin.c')
-rw-r--r--apps/open_plugin.c282
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
47static 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
43static inline void op_clear_entry(struct open_plugin_entry_t *entry) 55static 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
63static 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
52static int op_update_dat(struct open_plugin_entry_t *entry, bool clear) 95static 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)
88uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter) 177uint32_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 } 235retnhash:
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
156void open_plugin_browse(const char *key) 243void 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
175static 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
308static 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
316static 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
222int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry) 323int 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
231int open_plugin_run(const char *key) 349int 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
254void open_plugin_cache_flush(void) 373void 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