summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2024-07-02 10:14:59 -0400
committerWilliam Wilgus <me.theuser@yahoo.com>2024-07-04 12:44:04 -0400
commitb0dfcde2f5fb086e7a7f54b16a47e0433661cca7 (patch)
tree7336885079c98b5d0d3f245968882187164591ae
parent3e9ca6ec8ed5d452db482ae3cffb66e5330ec244 (diff)
downloadrockbox-b0dfcde2f5fb086e7a7f54b16a47e0433661cca7.tar.gz
rockbox-b0dfcde2f5fb086e7a7f54b16a47e0433661cca7.zip
[Cleanup] onplay.c fileop.c
clean-up a bit more add/correct some comments fix some error passing guard delete path on PATH_TOO_LONG add some cpu_boost Change-Id: Icf179dd727271bdc61ab78400e10847222b9f858
-rw-r--r--apps/fileop.c344
-rw-r--r--apps/fileop.h19
-rw-r--r--apps/onplay.c245
-rw-r--r--apps/onplay.h2
4 files changed, 300 insertions, 310 deletions
diff --git a/apps/fileop.c b/apps/fileop.c
index 0d2dc774b9..c4bdc5aa18 100644
--- a/apps/fileop.c
+++ b/apps/fileop.c
@@ -1,10 +1,10 @@
1/*************************************************************************** 1/***************************************************************************
2 * __________ __ ___. 2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2002 Björn Stenberg 10 * Copyright (C) 2002 Björn Stenberg
@@ -50,6 +50,17 @@ struct file_op_params
50 size_t append; /* Append position in 'path' for stack push */ 50 size_t append; /* Append position in 'path' for stack push */
51}; 51};
52 52
53static int prompt_name(char* buf, size_t bufsz)
54{
55 if (kbd_input(buf, bufsz, NULL) < 0)
56 return FORC_CANCELLED;
57 /* at least prevent escapes out of the base directory from keyboard-
58 entered filenames; the file code should reject other invalidities */
59 if (*buf != '\0' && !strchr(buf, PATH_SEPCH) && !is_dotdir_name(buf))
60 return FORC_SUCCESS;
61 return FORC_UNKNOWN_FAILURE;
62}
63
53static bool poll_cancel_action(const char *path, int operation, int current, int total) 64static bool poll_cancel_action(const char *path, int operation, int current, int total)
54{ 65{
55 const char *op_str = ""; 66 const char *op_str = "";
@@ -75,7 +86,7 @@ static bool poll_cancel_action(const char *path, int operation, int current, int
75 return ACTION_STD_CANCEL == get_action(CONTEXT_STD, TIMEOUT_NOBLOCK); 86 return ACTION_STD_CANCEL == get_action(CONTEXT_STD, TIMEOUT_NOBLOCK);
76} 87}
77 88
78static struct file_op_params* init_file_op(struct file_op_params *param, 89static void init_file_op(struct file_op_params *param,
79 const char *basename, 90 const char *basename,
80 const char *selected_file) 91 const char *selected_file)
81{ 92{
@@ -90,8 +101,6 @@ static struct file_op_params* init_file_op(struct file_op_params *param,
90 param->is_dir = dir_exists(param->path); 101 param->is_dir = dir_exists(param->path);
91 param->objects = 0; /* how many files and subdirectories*/ 102 param->objects = 0; /* how many files and subdirectories*/
92 param->processed = 0; 103 param->processed = 0;
93
94 return param;
95} 104}
96 105
97/* counts file objects, deletes file objects */ 106/* counts file objects, deletes file objects */
@@ -144,7 +153,7 @@ static int directory_fileop(struct file_op_params *param, enum file_op_current f
144 153
145 if (info.attribute & ATTR_DIRECTORY) { 154 if (info.attribute & ATTR_DIRECTORY) {
146 /* remove a subdirectory */ 155 /* remove a subdirectory */
147 rc = directory_fileop(param, fileop); 156 rc = directory_fileop(param, fileop); /* recursion */
148 } else { 157 } else {
149 /* remove a file */ 158 /* remove a file */
150 if (poll_cancel_action(param->path, FOC_DELETE, param->processed, param->objects)) 159 if (poll_cancel_action(param->path, FOC_DELETE, param->processed, param->objects))
@@ -165,8 +174,8 @@ static int directory_fileop(struct file_op_params *param, enum file_op_current f
165 } 174 }
166 175
167 if (info.attribute & ATTR_DIRECTORY) { 176 if (info.attribute & ATTR_DIRECTORY) {
168 /* remove a subdirectory */ 177 /* enter subdirectory */
169 rc = directory_fileop(param, FOC_COUNT); 178 rc = directory_fileop(param, FOC_COUNT); /* recursion */
170 } else { 179 } else {
171 if (poll_cancel_action(param->path, FOC_COUNT, param->objects, 0)) 180 if (poll_cancel_action(param->path, FOC_COUNT, param->objects, 0))
172 { 181 {
@@ -195,150 +204,42 @@ static int directory_fileop(struct file_op_params *param, enum file_op_current f
195 return rc; 204 return rc;
196} 205}
197 206
207/* Walk a directory tree and count the number of objects (dirs & files)
208 * also check that enough resources exist to do an operation */
198static int check_count_fileobjects(struct file_op_params *param) 209static int check_count_fileobjects(struct file_op_params *param)
199{ 210{
211 cpu_boost(true);
200 int rc = directory_fileop(param, FOC_COUNT); 212 int rc = directory_fileop(param, FOC_COUNT);
213 cpu_boost(false);
201 DEBUGF("%s res:(%d) objects %d \n", __func__, rc, param->objects); 214 DEBUGF("%s res:(%d) objects %d \n", __func__, rc, param->objects);
202 return rc; 215 return rc;
203} 216}
204 217
205static bool check_new_name(const char *basename) 218/* Attempt to just rename a file or directory */
206{
207 /* at least prevent escapes out of the base directory from keyboard-
208 entered filenames; the file code should reject other invalidities */
209 return *basename != '\0' && !strchr(basename, PATH_SEPCH) &&
210 !is_dotdir_name(basename);
211}
212
213int create_dir(void)
214{
215 int rc = FORC_UNKNOWN_FAILURE;
216 char dirname[MAX_PATH];
217 size_t pathlen = path_append(dirname, getcwd(NULL, 0), PA_SEP_HARD,
218 sizeof (dirname));
219 char *basename = dirname + pathlen;
220
221 if (pathlen >= sizeof (dirname)) {
222 /* Too long */
223 } else if (kbd_input(basename, sizeof (dirname) - pathlen, NULL) < 0) {
224 rc = FORC_CANCELLED;
225 } else if (check_new_name(basename)) {
226 rc = mkdir(dirname);
227 }
228
229 return rc;
230}
231
232/************************************************************************************/
233/* share code for file and directory deletion, saves space */
234static int delete_file_dir(struct file_op_params *param)
235{
236 /* Note: delete_file_dir() will happily delete whatever
237 * path is passed (after confirmation) */
238 if (confirm_delete_yesno(param->path) != YESNO_YES) {
239 return FORC_CANCELLED;
240 }
241
242 clear_screen_buffer(true);
243 poll_cancel_action(param->path, FOC_DELETE, param->processed, param->objects);
244
245 int rc = FORC_UNKNOWN_FAILURE;
246
247 if (param->is_dir) { /* if directory */
248 cpu_boost(true);
249 rc = directory_fileop(param, FOC_DELETE);
250 cpu_boost(false);
251 } else {
252 rc = remove(param->path);
253 }
254
255 return rc;
256}
257
258int delete_fileobject(const char *selected_file)
259{
260 struct file_op_params param;
261 if (init_file_op(&param, selected_file, NULL)->is_dir == true)
262 {
263 int rc = check_count_fileobjects(&param);
264 DEBUGF("%s res: %d, ct: %d, %s", __func__, rc, param.objects, param.path);
265 if (rc != FORC_SUCCESS)
266 return rc;
267 }
268
269 return delete_file_dir(&param);
270}
271
272int rename_file(const char *selected_file)
273{
274 int rc = FORC_UNKNOWN_FAILURE;
275 char newname[MAX_PATH];
276 const char *oldbase, *selection = selected_file;
277
278 path_basename(selection, &oldbase);
279 size_t pathlen = oldbase - selection;
280 char *newbase = newname + pathlen;
281
282 if (strmemccpy(newname, selection, sizeof (newname)) == NULL) {
283 /* Too long */
284 } else if (kbd_input(newbase, sizeof (newname) - pathlen, NULL) < 0) {
285 rc = FORC_CANCELLED;
286 } else if (!strcmp(oldbase, newbase)) {
287 rc = FORC_NOOP; /* No change at all */
288 } else if (check_new_name(newbase)) {
289 switch (relate(selection, newname))
290 {
291 case RELATE_DIFFERENT:
292 if (file_exists(newname)) {
293 break; /* don't overwrite */
294 }
295 /* Fall-through */
296 case RELATE_SAME:
297 rc = rename(selection, newname);
298 break;
299 case RELATE_PREFIX:
300 default:
301 break;
302 }
303 }
304
305 return rc;
306}
307
308static int move_by_rename(const char *src_path, 219static int move_by_rename(const char *src_path,
309 const char *dst_path, 220 const char *dst_path,
310 unsigned int *pflags) 221 unsigned int *pflags)
311{ 222{
312 unsigned int flags = *pflags; 223 unsigned int flags = *pflags;
313 int rc = FORC_UNKNOWN_FAILURE; 224 int rc = FORC_UNKNOWN_FAILURE;
314 while (!(flags & (PASTE_COPY | PASTE_EXDEV))) { 225 if (!(flags & (PASTE_COPY | PASTE_EXDEV))) {
315 if ((flags & PASTE_OVERWRITE) || !file_exists(dst_path)) { 226 if ((flags & PASTE_OVERWRITE) || !file_exists(dst_path)) {
316 /* Just try to move the directory / file */ 227 /* Just try to move the directory / file */
317 if (poll_cancel_action(src_path, FOC_MOVE, 0 , 0)) { 228 if (poll_cancel_action(src_path, FOC_MOVE, 0 , 0)) {
318 rc = FORC_CANCELLED; 229 rc = FORC_CANCELLED;
319 } else { 230 } else {
320 rc = rename(src_path, dst_path); 231 rc = rename(src_path, dst_path);
321 } 232#ifdef HAVE_MULTIVOLUME
322 233 if (rc < FORC_SUCCESS && errno == EXDEV) {
323 if (rc < 0) { 234 /* Failed because cross volume rename doesn't work */
324 int errnum = errno; 235 *pflags |= PASTE_EXDEV; /* force a move instead */
325 if (errnum == ENOTEMPTY && (flags & PASTE_OVERWRITE)) {
326 /* Directory is not empty thus rename() will not do a quick
327 overwrite */
328 break;
329 } 236 }
330 #ifdef HAVE_MULTIVOLUME 237#endif /* HAVE_MULTIVOLUME */
331 else if (errnum == EXDEV) { 238 /* if (errno == ENOTEMPTY && (flags & PASTE_OVERWRITE)) {
332 /* Failed because cross volume rename doesn't work; force 239 * Directory is not empty thus rename() will not do a quick overwrite */
333 a move instead */
334 *pflags |= PASTE_EXDEV;
335 break;
336 }
337 #endif /* HAVE_MULTIVOLUME */
338 } 240 }
339 } 241 }
340 242
341 break;
342 } 243 }
343 return rc; 244 return rc;
344} 245}
@@ -365,8 +266,7 @@ static int copy_move_file(const char *src_path, const char *dst_path, unsigned i
365 return FORC_NO_BUFFER_AVAIL; 266 return FORC_NO_BUFFER_AVAIL;
366 } 267 }
367 268
368 buffersize &= ~0x1ff; /* Round buffer size to multiple of sector 269 buffersize &= ~0x1ff; /* Round buffer size to multiple of sector size */
369 size */
370 270
371 int src_fd = open(src_path, O_RDONLY); 271 int src_fd = open(src_path, O_RDONLY);
372 if (src_fd >= 0) { 272 if (src_fd >= 0) {
@@ -423,9 +323,12 @@ static int copy_move_file(const char *src_path, const char *dst_path, unsigned i
423 } 323 }
424 324
425 if (rc == FORC_SUCCESS) { 325 if (rc == FORC_SUCCESS) {
426 /* If overwriting, set the correct length if original was 326 if (total_size != src_sz)
427 longer */ 327 rc = FORC_UNKNOWN_FAILURE;
428 rc = ftruncate(dst_fd, total_size) * 10; 328 else {
329 /* If overwriting, set the correct length if original was longer */
330 rc = ftruncate(dst_fd, total_size) * 10;
331 }
429 } 332 }
430 333
431 close(dst_fd); 334 close(dst_fd);
@@ -449,20 +352,19 @@ static int copy_move_file(const char *src_path, const char *dst_path, unsigned i
449 352
450/* Paste a directory */ 353/* Paste a directory */
451static int copy_move_directory(struct file_op_params *src, 354static int copy_move_directory(struct file_op_params *src,
452 struct file_op_params *dst, 355 struct file_op_params *dst,
453 unsigned int flags) 356 unsigned int flags)
454{ 357{
455 int rc = FORC_UNKNOWN_FAILURE;
456
457 DIR *srcdir = opendir(src->path); 358 DIR *srcdir = opendir(src->path);
458 359
459 if (srcdir) { 360 if (!srcdir)
460 /* Make a directory to copy things to */ 361 return FORC_PATH_NOT_EXIST;
461 rc = mkdir(dst->path) * 10; 362
462 if (rc < 0 && errno == EEXIST && (flags & PASTE_OVERWRITE)) { 363 /* Make a directory to copy things to */
463 /* Exists and overwrite was approved */ 364 int rc = mkdir(dst->path) * 10;
464 rc = FORC_SUCCESS; 365 if (rc < 0 && errno == EEXIST && (flags & PASTE_OVERWRITE)) {
465 } 366 /* Exists and overwrite was approved */
367 rc = FORC_SUCCESS;
466 } 368 }
467 369
468 size_t srcap = src->append, dstap = dst->append; 370 size_t srcap = src->append, dstap = dst->append;
@@ -488,7 +390,7 @@ static int copy_move_directory(struct file_op_params *src,
488 /* Append names to current directories */ 390 /* Append names to current directories */
489 src->append = srcap + 391 src->append = srcap +
490 path_append(&src->path[srcap], PA_SEP_HARD, entry->d_name, 392 path_append(&src->path[srcap], PA_SEP_HARD, entry->d_name,
491 sizeof(src->path) - srcap); 393 sizeof (src->path) - srcap);
492 394
493 dst->append = dstap + 395 dst->append = dstap +
494 path_append(&dst->path[dstap], PA_SEP_HARD, entry->d_name, 396 path_append(&dst->path[dstap], PA_SEP_HARD, entry->d_name,
@@ -538,13 +440,16 @@ static int copy_move_directory(struct file_op_params *src,
538 return rc; 440 return rc;
539} 441}
540 442
443/************************************************************************************/
444/* PUBLIC FUNCTIONS */
445/************************************************************************************/
446
447/* Copy or move a file or directory see: file_op_flags */
541int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned int flags) 448int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned int flags)
542{ 449{
543 if (!src_path[0]) 450 if (!src_path[0])
544 return FORC_NOOP; 451 return FORC_NOOP;
545 452
546 int rc = FORC_UNKNOWN_FAILURE;
547
548 struct file_op_params src, dst; 453 struct file_op_params src, dst;
549 454
550 /* Figure out the name of the selection */ 455 /* Figure out the name of the selection */
@@ -553,40 +458,37 @@ int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned in
553 458
554 /* Final target is current directory plus name of selection */ 459 /* Final target is current directory plus name of selection */
555 init_file_op(&dst, dst_path, nameptr); 460 init_file_op(&dst, dst_path, nameptr);
461 if (dst.append >= sizeof (dst.path))
462 return FORC_PATH_TOO_LONG;
556 463
557 switch (dst.append < sizeof (dst.path) ? 464 int rel = relate(src_path, dst.path);
558 relate(src_path, dst.path) : FORC_PATH_TOO_LONG) 465 if (rel == RELATE_SAME)
559 { 466 return FORC_NOOP;
560 case RELATE_SAME:
561 rc = FORC_NOOP;
562 break;
563 467
564 case RELATE_DIFFERENT: 468 if (rel == RELATE_DIFFERENT) {
469 int rc;
565 if (file_exists(dst.path)) { 470 if (file_exists(dst.path)) {
566 /* If user chooses not to overwrite, cancel */ 471 /* If user chooses not to overwrite, cancel */
567 if (confirm_overwrite_yesno() == YESNO_NO) { 472 if (confirm_overwrite_yesno() == YESNO_NO) {
568 rc = FORC_NOOVERWRT; 473 return FORC_NOOVERWRT;
569 break;
570 } 474 }
571 475
572 flags |= PASTE_OVERWRITE; 476 flags |= PASTE_OVERWRITE;
573 } 477 }
574 478
479 init_file_op(&src, src_path, NULL);
480 if (src.append >= sizeof (src.path))
481 return FORC_PATH_TOO_LONG;
575 /* Now figure out what we're doing */ 482 /* Now figure out what we're doing */
576 cpu_boost(true); 483 cpu_boost(true);
577
578 init_file_op(&src, src_path, NULL);
579
580 if (src.is_dir) { 484 if (src.is_dir) {
581 /* Copy or move a subdirectory */ 485 /* Copy or move a subdirectory */
582 486 /* Try renaming first */
583 if (src.append < sizeof (src.path)) { 487 rc = move_by_rename(src.path, dst.path, &flags);
584 /* Try renaming first */ 488 if (rc < FORC_SUCCESS) {
585 rc = move_by_rename(src.path, dst.path, &flags); 489 rc = check_count_fileobjects(&src);
586 if (rc != FORC_SUCCESS && rc != FORC_CANCELLED) { 490 if (rc == FORC_SUCCESS) {
587 if (check_count_fileobjects(&src) == FORC_SUCCESS) { 491 rc = copy_move_directory(&src, &dst, flags);
588 rc = copy_move_directory(&src, &dst, flags);
589 }
590 } 492 }
591 } 493 }
592 } else { 494 } else {
@@ -595,12 +497,102 @@ int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned in
595 } 497 }
596 498
597 cpu_boost(false); 499 cpu_boost(false);
598 break; 500 DEBUGF("%s res: %d, ct: %d/%d %s\n",
501 __func__, rc, src.objects, src.processed, src.path);
502 return rc;
503 }
504
505 /* Else Some other relation / failure */
506 DEBUGF("%s res: %d, rel: %d\n", __func__, rc, rel);
507 return FORC_UNKNOWN_FAILURE;
508}
509
510int create_dir(void)
511{
512 int rc;
513 char dirname[MAX_PATH];
514 size_t pathlen = path_append(dirname, getcwd(NULL, 0), PA_SEP_HARD,
515 sizeof (dirname));
516 char *basename = dirname + pathlen;
517
518 if (pathlen >= sizeof (dirname))
519 return FORC_PATH_TOO_LONG;
520
521 rc = prompt_name(basename, sizeof (dirname) - pathlen);
522 if (rc == FORC_SUCCESS)
523 rc = mkdir(dirname) * 10;
524 return rc;
525}
599 526
600 case RELATE_PREFIX: 527/* share code for file and directory deletion, saves space */
601 default: /* Some other relation / failure */ 528int delete_fileobject(const char *selected_file)
602 break; 529{
530 int rc;
531 struct file_op_params param;
532 init_file_op(&param, selected_file, NULL);
533 if (param.append >= sizeof (param.path))
534 return FORC_PATH_TOO_LONG;
535
536 if (param.is_dir) {
537 int rc = check_count_fileobjects(&param);
538 DEBUGF("%s res: %d, ct: %d, %s", __func__, rc, param.objects, param.path);
539 if (rc != FORC_SUCCESS)
540 return rc;
541 }
542
543 /* Note: delete_fileobject() will happily delete whatever
544 * path is passed (after confirmation) */
545 if (confirm_delete_yesno(param.path) != YESNO_YES) {
546 return FORC_CANCELLED;
547 }
548
549 clear_screen_buffer(true);
550 if (poll_cancel_action(param.path, FOC_DELETE, param.processed, param.objects))
551 return FORC_CANCELLED;
552
553 if (param.is_dir) { /* if directory */
554 cpu_boost(true);
555 rc = directory_fileop(&param, FOC_DELETE);
556 cpu_boost(false);
557 } else {
558 rc = remove(param.path) * 10;
603 } 559 }
604 560
605 return rc; 561 return rc;
606} 562}
563
564int rename_file(const char *selected_file)
565{
566 int rc;
567 char newname[MAX_PATH];
568 const char *oldbase, *selection = selected_file;
569
570 path_basename(selection, &oldbase);
571 size_t pathlen = oldbase - selection;
572 char *newbase = newname + pathlen;
573
574 if (strmemccpy(newname, selection, sizeof (newname)) == NULL)
575 return FORC_PATH_TOO_LONG;
576
577 rc = prompt_name(newbase, sizeof (newname) - pathlen);
578
579 if (rc != FORC_SUCCESS)
580 return rc;
581
582 if (!strcmp(oldbase, newbase))
583 return FORC_NOOP; /* No change at all */
584
585 int rel = relate(selection, newname);
586 if (rel == RELATE_DIFFERENT)
587 {
588 if (file_exists(newname)) { /* don't overwrite */
589 return FORC_PATH_EXISTS;
590 }
591 return rename(selection, newname) * 10;
592 }
593 if (rel == RELATE_SAME)
594 return rename(selection, newname) * 10;
595
596 /* Else Some other relation / failure */
597 return FORC_UNKNOWN_FAILURE;
598}
diff --git a/apps/fileop.h b/apps/fileop.h
index f8237dc64f..f477549977 100644
--- a/apps/fileop.h
+++ b/apps/fileop.h
@@ -1,10 +1,10 @@
1/*************************************************************************** 1/***************************************************************************
2 * __________ __ ___. 2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2002 Björn Stenberg 10 * Copyright (C) 2002 Björn Stenberg
@@ -26,6 +26,7 @@
26/* result codes of various file operations */ 26/* result codes of various file operations */
27enum fileop_result_code 27enum fileop_result_code
28{ 28{
29 FORC_PATH_EXISTS = -8,
29 FORC_READ_FAILURE = -7, 30 FORC_READ_FAILURE = -7,
30 FORC_WRITE_FAILURE = -6, 31 FORC_WRITE_FAILURE = -6,
31 FORC_NO_BUFFER_AVAIL = -5, 32 FORC_NO_BUFFER_AVAIL = -5,
@@ -55,7 +56,6 @@ enum file_op_current
55 FOC_MOVE, 56 FOC_MOVE,
56 FOC_COPY, 57 FOC_COPY,
57 FOC_DELETE, 58 FOC_DELETE,
58 FOC_CREATE,
59}; 59};
60 60
61int create_dir(void); 61int create_dir(void);
@@ -64,7 +64,8 @@ int rename_file(const char *selected_file);
64 64
65int delete_fileobject(const char *selected_file); 65int delete_fileobject(const char *selected_file);
66 66
67int copy_move_fileobject(const char *src_path, const char *dst_path, 67int copy_move_fileobject(const char *src_path,
68 unsigned int flags); 68 const char *dst_path,
69 unsigned int flags);
69 70
70#endif /* FILEOP_H */ 71#endif /* FILEOP_H */
diff --git a/apps/onplay.c b/apps/onplay.c
index 4880af58f3..d468c0a545 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -65,12 +65,9 @@
65#include "shortcuts.h" 65#include "shortcuts.h"
66#include "misc.h" 66#include "misc.h"
67 67
68static int context;
69static const char *selected_file = NULL;
70static char selected_file_path[MAX_PATH];
71static int selected_file_attr = 0;
72static int onplay_result = ONPLAY_OK; 68static int onplay_result = ONPLAY_OK;
73static bool in_queue_submenu = false; 69static bool in_queue_submenu = false;
70
74static bool (*ctx_current_playlist_insert)(int position, bool queue, bool create_new); 71static bool (*ctx_current_playlist_insert)(int position, bool queue, bool create_new);
75static int (*ctx_add_to_playlist)(const char* playlist, bool new_playlist); 72static int (*ctx_add_to_playlist)(const char* playlist, bool new_playlist);
76extern struct menu_item_ex file_menu; /* settings_menu.c */ 73extern struct menu_item_ex file_menu; /* settings_menu.c */
@@ -84,6 +81,14 @@ extern struct menu_item_ex file_menu; /* settings_menu.c */
84 MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \ 81 MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \
85 { (void*)name##_},{.callback_and_desc = & name##__}}; 82 { (void*)name##_},{.callback_and_desc = & name##__}};
86 83
84static struct selected_file
85{
86 char buf[MAX_PATH];
87 const char *path;
88 int attr;
89 int context;
90} selected_file;
91
87static struct clipboard 92static struct clipboard
88{ 93{
89 char path[MAX_PATH]; /* Clipped file's path */ 94 char path[MAX_PATH]; /* Clipped file's path */
@@ -91,6 +96,14 @@ static struct clipboard
91 unsigned int flags; /* Operation type flags */ 96 unsigned int flags; /* Operation type flags */
92} clipboard; 97} clipboard;
93 98
99/* set selected file (doesn't touch buffer) */
100static void selected_file_set(int context, const char *path, int attr)
101{
102 selected_file.path = path;
103 selected_file.attr = attr;
104 selected_file.context = context;
105}
106
94/* Empty the clipboard */ 107/* Empty the clipboard */
95static void clipboard_clear_selection(struct clipboard *clip) 108static void clipboard_clear_selection(struct clipboard *clip)
96{ 109{
@@ -149,20 +162,18 @@ static int bookmark_menu_callback(int action,
149 struct gui_synclist *this_list) 162 struct gui_synclist *this_list)
150{ 163{
151 (void) this_list; 164 (void) this_list;
152 switch (action) 165 if (action == ACTION_REQUEST_MENUITEM)
153 { 166 {
154 case ACTION_REQUEST_MENUITEM: 167 /* hide loading bookmarks menu if no bookmarks exist */
155 /* hide loading bookmarks menu if no bookmarks exist */ 168 if (this_item == &bookmark_load_menu_item)
156 if (this_item == &bookmark_load_menu_item) 169 {
157 { 170 if (!bookmark_exists())
158 if (!bookmark_exists()) 171 return ACTION_EXIT_MENUITEM;
159 return ACTION_EXIT_MENUITEM; 172 }
160 }
161 break;
162 case ACTION_EXIT_MENUITEM:
163 settings_save();
164 break;
165 } 173 }
174 else if (action == ACTION_EXIT_MENUITEM)
175 settings_save();
176
166 return action; 177 return action;
167} 178}
168 179
@@ -244,20 +255,20 @@ static struct add_to_pl_param addtopl_replace_shuffled = {PLAYLIST_INSERT_LAST_S
244static void op_playlist_insert_selected(int position, bool queue) 255static void op_playlist_insert_selected(int position, bool queue)
245{ 256{
246#ifdef HAVE_TAGCACHE 257#ifdef HAVE_TAGCACHE
247 if (context == CONTEXT_STD && ctx_current_playlist_insert != NULL) 258 if (selected_file.context == CONTEXT_STD && ctx_current_playlist_insert != NULL)
248 { 259 {
249 ctx_current_playlist_insert(position, queue, false); 260 ctx_current_playlist_insert(position, queue, false);
250 return; 261 return;
251 } 262 }
252#endif 263#endif
253 if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) 264 if ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO)
254 playlist_insert_track(NULL, selected_file, position, queue, true); 265 playlist_insert_track(NULL, selected_file.path, position, queue, true);
255 else if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U) 266 else if ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_M3U)
256 playlist_insert_playlist(NULL, selected_file, position, queue); 267 playlist_insert_playlist(NULL, selected_file.path, position, queue);
257 else if (selected_file_attr & ATTR_DIRECTORY) 268 else if (selected_file.attr & ATTR_DIRECTORY)
258 { 269 {
259#ifdef HAVE_TAGCACHE 270#ifdef HAVE_TAGCACHE
260 if (context == CONTEXT_ID3DB) 271 if (selected_file.context == CONTEXT_ID3DB)
261 { 272 {
262 tagtree_current_playlist_insert(position, queue); 273 tagtree_current_playlist_insert(position, queue);
263 return; 274 return;
@@ -269,14 +280,14 @@ static void op_playlist_insert_selected(int position, bool queue)
269 280
270 const char *lines[] = { 281 const char *lines[] = {
271 ID2P(LANG_RECURSE_DIRECTORY_QUESTION), 282 ID2P(LANG_RECURSE_DIRECTORY_QUESTION),
272 selected_file 283 selected_file.path
273 }; 284 };
274 const struct text_message message={lines, 2}; 285 const struct text_message message={lines, 2};
275 /* Ask if user wants to recurse directory */ 286 /* Ask if user wants to recurse directory */
276 recurse = (gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES); 287 recurse = (gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES);
277 } 288 }
278 289
279 playlist_insert_directory(NULL, selected_file, position, queue, 290 playlist_insert_directory(NULL, selected_file.path, position, queue,
280 recurse == RECURSE_ON); 291 recurse == RECURSE_ON);
281 } 292 }
282} 293}
@@ -336,7 +347,7 @@ static bool view_playlist(void)
336{ 347{
337 bool result; 348 bool result;
338 349
339 result = playlist_viewer_ex(selected_file, NULL); 350 result = playlist_viewer_ex(selected_file.path, NULL);
340 351
341 if (result == PLAYLIST_VIEWER_OK && 352 if (result == PLAYLIST_VIEWER_OK &&
342 onplay_result == ONPLAY_OK) 353 onplay_result == ONPLAY_OK)
@@ -431,7 +442,7 @@ static int treeplaylist_callback(int action,
431 struct gui_synclist *this_list) 442 struct gui_synclist *this_list)
432{ 443{
433 (void)this_list; 444 (void)this_list;
434 int sel_file_attr = (selected_file_attr & FILE_ATTR_MASK); 445 int sel_file_attr = (selected_file.attr & FILE_ATTR_MASK);
435 446
436 switch (action) 447 switch (action)
437 { 448 {
@@ -440,7 +451,7 @@ static int treeplaylist_callback(int action,
440 { 451 {
441 if (sel_file_attr != FILE_ATTR_AUDIO && 452 if (sel_file_attr != FILE_ATTR_AUDIO &&
442 sel_file_attr != FILE_ATTR_M3U && 453 sel_file_attr != FILE_ATTR_M3U &&
443 (selected_file_attr & ATTR_DIRECTORY) == 0) 454 (selected_file.attr & ATTR_DIRECTORY) == 0)
444 return ACTION_EXIT_MENUITEM; 455 return ACTION_EXIT_MENUITEM;
445 } 456 }
446 else if (this_item == &queue_menu) 457 else if (this_item == &queue_menu)
@@ -471,7 +482,7 @@ static int treeplaylist_callback(int action,
471 return ACTION_EXIT_MENUITEM; 482 return ACTION_EXIT_MENUITEM;
472 483
473 if (sel_file_attr != FILE_ATTR_M3U && 484 if (sel_file_attr != FILE_ATTR_M3U &&
474 (selected_file_attr & ATTR_DIRECTORY) == 0) 485 (selected_file.attr & ATTR_DIRECTORY) == 0)
475 return ACTION_EXIT_MENUITEM; 486 return ACTION_EXIT_MENUITEM;
476 } 487 }
477 488
@@ -494,10 +505,8 @@ static int treeplaylist_callback(int action,
494 505
495void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_insert_cb)) 506void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_insert_cb))
496{ 507{
497 context = CONTEXT_STD;
498 ctx_current_playlist_insert = playlist_insert_cb; 508 ctx_current_playlist_insert = playlist_insert_cb;
499 selected_file = path; 509 selected_file_set(CONTEXT_STD, path, attr);
500 selected_file_attr = attr;
501 in_queue_submenu = false; 510 in_queue_submenu = false;
502 do_menu(&tree_playlist_menu, NULL, NULL, false); 511 do_menu(&tree_playlist_menu, NULL, NULL, false);
503} 512}
@@ -505,13 +514,13 @@ void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_inser
505/* playlist catalog options */ 514/* playlist catalog options */
506static bool cat_add_to_a_playlist(void) 515static bool cat_add_to_a_playlist(void)
507{ 516{
508 return catalog_add_to_a_playlist(selected_file, selected_file_attr, 517 return catalog_add_to_a_playlist(selected_file.path, selected_file.attr,
509 false, NULL, ctx_add_to_playlist); 518 false, NULL, ctx_add_to_playlist);
510} 519}
511 520
512static bool cat_add_to_a_new_playlist(void) 521static bool cat_add_to_a_new_playlist(void)
513{ 522{
514 return catalog_add_to_a_playlist(selected_file, selected_file_attr, 523 return catalog_add_to_a_playlist(selected_file.path, selected_file.attr,
515 true, NULL, ctx_add_to_playlist); 524 true, NULL, ctx_add_to_playlist);
516} 525}
517 526
@@ -529,10 +538,8 @@ MAKE_ONPLAYMENU(cat_playlist_menu, ID2P(LANG_ADD_TO_PL),
529 538
530void onplay_show_playlist_cat_menu(const char* track_name, int attr, void (*add_to_pl_cb)) 539void onplay_show_playlist_cat_menu(const char* track_name, int attr, void (*add_to_pl_cb))
531{ 540{
532 context = CONTEXT_STD;
533 ctx_add_to_playlist = add_to_pl_cb; 541 ctx_add_to_playlist = add_to_pl_cb;
534 selected_file = track_name; 542 selected_file_set(CONTEXT_STD, track_name, attr);
535 selected_file_attr = attr;
536 do_menu(&cat_playlist_menu, NULL, NULL, false); 543 do_menu(&cat_playlist_menu, NULL, NULL, false);
537} 544}
538 545
@@ -542,24 +549,22 @@ static int cat_playlist_callback(int action,
542{ 549{
543 (void)this_item; 550 (void)this_item;
544 (void)this_list; 551 (void)this_list;
545 if (!selected_file || 552 if (!selected_file.path ||
546 (((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) && 553 (((selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) &&
547 ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) && 554 ((selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) &&
548 ((selected_file_attr & ATTR_DIRECTORY) == 0))) 555 ((selected_file.attr & ATTR_DIRECTORY) == 0)))
549 { 556 {
550 return ACTION_EXIT_MENUITEM; 557 return ACTION_EXIT_MENUITEM;
551 } 558 }
552 559
553 switch (action) 560 if (action == ACTION_REQUEST_MENUITEM)
554 { 561 {
555 case ACTION_REQUEST_MENUITEM: 562 if ((audio_status() & AUDIO_STATUS_PLAY)
556 if ((audio_status() & AUDIO_STATUS_PLAY) || context != CONTEXT_WPS) 563 || selected_file.context != CONTEXT_WPS)
557 { 564 {
558 return action; 565 return action;
559 } 566 }
560 else 567 return ACTION_EXIT_MENUITEM;
561 return ACTION_EXIT_MENUITEM;
562 break;
563 } 568 }
564 return action; 569 return action;
565} 570}
@@ -579,13 +584,13 @@ static void splash_failed(int lang_what, int err)
579 584
580static bool clipboard_cut(void) 585static bool clipboard_cut(void)
581{ 586{
582 return clipboard_clip(&clipboard, selected_file, selected_file_attr, 587 return clipboard_clip(&clipboard, selected_file.path, selected_file.attr,
583 PASTE_CUT); 588 PASTE_CUT);
584} 589}
585 590
586static bool clipboard_copy(void) 591static bool clipboard_copy(void)
587{ 592{
588 return clipboard_clip(&clipboard, selected_file, selected_file_attr, 593 return clipboard_clip(&clipboard, selected_file.path, selected_file.attr,
589 PASTE_COPY); 594 PASTE_COPY);
590} 595}
591 596
@@ -597,9 +602,6 @@ static int clipboard_paste(void)
597 602
598 int rc = copy_move_fileobject(clipboard.path, getcwd(NULL, 0), clipboard.flags); 603 int rc = copy_move_fileobject(clipboard.path, getcwd(NULL, 0), clipboard.flags);
599 604
600
601 clear_screen_buffer(true);
602
603 switch (rc) 605 switch (rc)
604 { 606 {
605 case FORC_CANCELLED: 607 case FORC_CANCELLED:
@@ -643,13 +645,10 @@ static int ratingitem_callback(int action,
643{ 645{
644 (void)this_item; 646 (void)this_item;
645 (void)this_list; 647 (void)this_list;
646 switch (action) 648 if (action == ACTION_REQUEST_MENUITEM)
647 { 649 {
648 case ACTION_REQUEST_MENUITEM: 650 if (!selected_file.path || !global_settings.runtimedb || !tagcache_is_usable())
649 if (!selected_file || !global_settings.runtimedb || 651 return ACTION_EXIT_MENUITEM;
650 !tagcache_is_usable())
651 return ACTION_EXIT_MENUITEM;
652 break;
653 } 652 }
654 return action; 653 return action;
655} 654}
@@ -676,13 +675,10 @@ static int view_cue_item_callback(int action,
676 (void)this_item; 675 (void)this_item;
677 (void)this_list; 676 (void)this_list;
678 struct mp3entry* id3 = audio_current_track(); 677 struct mp3entry* id3 = audio_current_track();
679 switch (action) 678 if (action == ACTION_REQUEST_MENUITEM)
680 { 679 {
681 case ACTION_REQUEST_MENUITEM: 680 if (!selected_file.path || !id3 || !id3->cuesheet)
682 if (!selected_file 681 return ACTION_EXIT_MENUITEM;
683 || !id3 || !id3->cuesheet)
684 return ACTION_EXIT_MENUITEM;
685 break;
686 } 682 }
687 return action; 683 return action;
688} 684}
@@ -712,7 +708,7 @@ MENUITEM_FUNCTION(pitch_screen_item, 0, ID2P(LANG_PITCH),
712 708
713static int clipboard_delete_selected_fileobject(void) 709static int clipboard_delete_selected_fileobject(void)
714{ 710{
715 int rc = delete_fileobject(selected_file); 711 int rc = delete_fileobject(selected_file.path);
716 if (rc < FORC_SUCCESS) { 712 if (rc < FORC_SUCCESS) {
717 splash_failed(LANG_DELETE, rc); 713 splash_failed(LANG_DELETE, rc);
718 } else if (rc == FORC_CANCELLED) { 714 } else if (rc == FORC_CANCELLED) {
@@ -747,7 +743,7 @@ static int clipboard_create_dir(void)
747 743
748static int clipboard_rename_selected_file(void) 744static int clipboard_rename_selected_file(void)
749{ 745{
750 int rc = rename_file(selected_file); 746 int rc = rename_file(selected_file.path);
751 747
752 show_result(rc, LANG_RENAME); 748 show_result(rc, LANG_RENAME);
753 749
@@ -777,7 +773,7 @@ MENUITEM_FUNCTION(create_dir_item, 0, ID2P(LANG_CREATE_DIR),
777/* other items */ 773/* other items */
778static bool list_viewers(void) 774static bool list_viewers(void)
779{ 775{
780 int ret = filetype_list_viewers(selected_file); 776 int ret = filetype_list_viewers(selected_file.path);
781 if (ret == PLUGIN_USB_CONNECTED) 777 if (ret == PLUGIN_USB_CONNECTED)
782 onplay_result = ONPLAY_RELOAD_DIR; 778 onplay_result = ONPLAY_RELOAD_DIR;
783 return false; 779 return false;
@@ -786,19 +782,19 @@ static bool list_viewers(void)
786#ifdef HAVE_TAGCACHE 782#ifdef HAVE_TAGCACHE
787static bool prepare_database_sel(void *param) 783static bool prepare_database_sel(void *param)
788{ 784{
789 if (context == CONTEXT_ID3DB && 785 if (selected_file.context == CONTEXT_ID3DB &&
790 (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) 786 (selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO)
791 { 787 {
792 if (!strcmp(param, "properties")) 788 if (!strcmp(param, "properties"))
793 strmemccpy(selected_file_path, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER), 789 strmemccpy(selected_file.buf, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER),
794 sizeof(selected_file_path)); 790 sizeof(selected_file.buf));
795 else if (!tagtree_get_subentry_filename(selected_file_path, MAX_PATH)) 791 else if (!tagtree_get_subentry_filename(selected_file.buf, MAX_PATH))
796 { 792 {
797 onplay_result = ONPLAY_RELOAD_DIR; 793 onplay_result = ONPLAY_RELOAD_DIR;
798 return false; 794 return false;
799 } 795 }
800 796
801 selected_file = selected_file_path; 797 selected_file.path = selected_file.buf;
802 } 798 }
803 return true; 799 return true;
804} 800}
@@ -810,7 +806,7 @@ static bool onplay_load_plugin(void *param)
810 if (!prepare_database_sel(param)) 806 if (!prepare_database_sel(param))
811 return false; 807 return false;
812#endif 808#endif
813 int ret = filetype_load_plugin((const char*)param, selected_file); 809 int ret = filetype_load_plugin((const char*)param, selected_file.path);
814 if (ret == PLUGIN_USB_CONNECTED) 810 if (ret == PLUGIN_USB_CONNECTED)
815 onplay_result = ONPLAY_RELOAD_DIR; 811 onplay_result = ONPLAY_RELOAD_DIR;
816 else if (ret == PLUGIN_GOTO_PLUGIN) 812 else if (ret == PLUGIN_GOTO_PLUGIN)
@@ -835,7 +831,7 @@ MENUITEM_FUNCTION_W_PARAM(pictureflow_item, 0, ID2P(LANG_ONPLAY_PICTUREFLOW),
835#endif 831#endif
836static bool onplay_add_to_shortcuts(void) 832static bool onplay_add_to_shortcuts(void)
837{ 833{
838 shortcuts_add(SHORTCUT_BROWSER, selected_file); 834 shortcuts_add(SHORTCUT_BROWSER, selected_file.path);
839 return false; 835 return false;
840} 836}
841MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES), 837MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES),
@@ -844,7 +840,7 @@ MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES),
844 840
845static void set_dir_helper(char* dirnamebuf, size_t bufsz) 841static void set_dir_helper(char* dirnamebuf, size_t bufsz)
846{ 842{
847 path_append(dirnamebuf, selected_file, PA_SEP_HARD, bufsz); 843 path_append(dirnamebuf, selected_file.path, PA_SEP_HARD, bufsz);
848 settings_save(); 844 settings_save();
849} 845}
850 846
@@ -882,7 +878,7 @@ MENUITEM_FUNCTION(set_startdir_item, 0, ID2P(LANG_START_DIR),
882 878
883static bool set_catalogdir(void) 879static bool set_catalogdir(void)
884{ 880{
885 catalog_set_directory(selected_file); 881 catalog_set_directory(selected_file.path);
886 settings_save(); 882 settings_save();
887 return false; 883 return false;
888} 884}
@@ -893,7 +889,7 @@ MENUITEM_FUNCTION(set_catalogdir_item, 0, ID2P(LANG_PLAYLIST_DIR),
893static bool set_databasedir(void) 889static bool set_databasedir(void)
894{ 890{
895 struct tagcache_stat *tc_stat = tagcache_get_stat(); 891 struct tagcache_stat *tc_stat = tagcache_get_stat();
896 if (strcasecmp(selected_file, tc_stat->db_path)) 892 if (strcasecmp(selected_file.path, tc_stat->db_path))
897 { 893 {
898 splash(HZ, ID2P(LANG_PLEASE_REBOOT)); 894 splash(HZ, ID2P(LANG_PLEASE_REBOOT));
899 } 895 }
@@ -927,7 +923,7 @@ static int clipboard_callback(int action,
927 case ACTION_REQUEST_MENUITEM: 923 case ACTION_REQUEST_MENUITEM:
928#ifdef HAVE_MULTIVOLUME 924#ifdef HAVE_MULTIVOLUME
929 /* no rename+delete for volumes */ 925 /* no rename+delete for volumes */
930 if ((selected_file_attr & ATTR_VOLUME) && 926 if ((selected_file.attr & ATTR_VOLUME) &&
931 (this_item == &rename_file_item || 927 (this_item == &rename_file_item ||
932 this_item == &delete_dir_item || 928 this_item == &delete_dir_item ||
933 this_item == &clipboard_cut_item || 929 this_item == &clipboard_cut_item ||
@@ -935,7 +931,7 @@ static int clipboard_callback(int action,
935 return ACTION_EXIT_MENUITEM; 931 return ACTION_EXIT_MENUITEM;
936#endif 932#endif
937#ifdef HAVE_TAGCACHE 933#ifdef HAVE_TAGCACHE
938 if (context == CONTEXT_ID3DB) 934 if (selected_file.context == CONTEXT_ID3DB)
939 { 935 {
940 if (this_item == &track_info_item || 936 if (this_item == &track_info_item ||
941 this_item == &pictureflow_item) 937 this_item == &pictureflow_item)
@@ -953,21 +949,21 @@ static int clipboard_callback(int action,
953 { 949 {
954 return action; 950 return action;
955 } 951 }
956 else if (selected_file) 952 else if (selected_file.path)
957 { 953 {
958 /* requires an actual file */ 954 /* requires an actual file */
959 if (this_item == &rename_file_item || 955 if (this_item == &rename_file_item ||
960 this_item == &clipboard_cut_item || 956 this_item == &clipboard_cut_item ||
961 this_item == &clipboard_copy_item || 957 this_item == &clipboard_copy_item ||
962 (this_item == &track_info_item && 958 (this_item == &track_info_item &&
963 (selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) || 959 (selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) ||
964 (this_item == &properties_item && 960 (this_item == &properties_item &&
965 (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) || 961 (selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) ||
966 this_item == &add_to_faves_item) 962 this_item == &add_to_faves_item)
967 { 963 {
968 return action; 964 return action;
969 } 965 }
970 else if ((selected_file_attr & ATTR_DIRECTORY)) 966 else if ((selected_file.attr & ATTR_DIRECTORY))
971 { 967 {
972 /* only for directories */ 968 /* only for directories */
973 if (this_item == &delete_dir_item || 969 if (this_item == &delete_dir_item ||
@@ -992,7 +988,7 @@ static int clipboard_callback(int action,
992#if LCD_DEPTH > 1 988#if LCD_DEPTH > 1
993 else if (this_item == &set_backdrop_item) 989 else if (this_item == &set_backdrop_item)
994 { 990 {
995 char *suffix = strrchr(selected_file, '.'); 991 char *suffix = strrchr(selected_file.path, '.');
996 if (suffix) 992 if (suffix)
997 { 993 {
998 if (strcasecmp(suffix, ".bmp") == 0) 994 if (strcasecmp(suffix, ".bmp") == 0)
@@ -1066,8 +1062,8 @@ static int onplaymenu_callback(int action,
1066 case ACTION_REQUEST_MENUITEM: 1062 case ACTION_REQUEST_MENUITEM:
1067 if (this_item == &view_playlist_item) 1063 if (this_item == &view_playlist_item)
1068 { 1064 {
1069 if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U && 1065 if ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_M3U &&
1070 context == CONTEXT_TREE) 1066 selected_file.context == CONTEXT_TREE)
1071 return action; 1067 return action;
1072 } 1068 }
1073 return ACTION_EXIT_MENUITEM; 1069 return ACTION_EXIT_MENUITEM;
@@ -1075,6 +1071,8 @@ static int onplaymenu_callback(int action,
1075 case ACTION_EXIT_MENUITEM: 1071 case ACTION_EXIT_MENUITEM:
1076 return ACTION_EXIT_AFTER_THIS_MENUITEM; 1072 return ACTION_EXIT_AFTER_THIS_MENUITEM;
1077 break; 1073 break;
1074 default:
1075 break;
1078 } 1076 }
1079 return action; 1077 return action;
1080} 1078}
@@ -1085,13 +1083,13 @@ static bool hotkey_delete_item(void)
1085{ 1083{
1086#ifdef HAVE_MULTIVOLUME 1084#ifdef HAVE_MULTIVOLUME
1087 /* no delete for volumes */ 1085 /* no delete for volumes */
1088 if (selected_file_attr & ATTR_VOLUME) 1086 if (selected_file.attr & ATTR_VOLUME)
1089 return false; 1087 return false;
1090#endif 1088#endif
1091 1089
1092#ifdef HAVE_TAGCACHE 1090#ifdef HAVE_TAGCACHE
1093 if (context == CONTEXT_ID3DB && 1091 if (selected_file.context == CONTEXT_ID3DB &&
1094 (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) 1092 (selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO)
1095 return false; 1093 return false;
1096#endif 1094#endif
1097 1095
@@ -1101,10 +1099,10 @@ static bool hotkey_delete_item(void)
1101static bool hotkey_open_with(void) 1099static bool hotkey_open_with(void)
1102{ 1100{
1103 /* only open files */ 1101 /* only open files */
1104 if (selected_file_attr & ATTR_DIRECTORY) 1102 if (selected_file.attr & ATTR_DIRECTORY)
1105 return false; 1103 return false;
1106#ifdef HAVE_MULTIVOLUME 1104#ifdef HAVE_MULTIVOLUME
1107 if (selected_file_attr & ATTR_VOLUME) 1105 if (selected_file.attr & ATTR_VOLUME)
1108 return false; 1106 return false;
1109#endif 1107#endif
1110 return list_viewers(); 1108 return list_viewers();
@@ -1113,8 +1111,8 @@ static bool hotkey_open_with(void)
1113static int hotkey_tree_pl_insert_shuffled(void) 1111static int hotkey_tree_pl_insert_shuffled(void)
1114{ 1112{
1115 if ((audio_status() & AUDIO_STATUS_PLAY) || 1113 if ((audio_status() & AUDIO_STATUS_PLAY) ||
1116 (selected_file_attr & ATTR_DIRECTORY) || 1114 (selected_file.attr & ATTR_DIRECTORY) ||
1117 ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U)) 1115 ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_M3U))
1118 { 1116 {
1119 add_to_playlist(&addtopl_insert_shuf); 1117 add_to_playlist(&addtopl_insert_shuf);
1120 } 1118 }
@@ -1127,7 +1125,7 @@ static int hotkey_tree_run_plugin(void *param)
1127 if (!prepare_database_sel(param)) 1125 if (!prepare_database_sel(param))
1128 return ONPLAY_RELOAD_DIR; 1126 return ONPLAY_RELOAD_DIR;
1129#endif 1127#endif
1130 if (filetype_load_plugin((const char*)param, selected_file) == PLUGIN_GOTO_WPS) 1128 if (filetype_load_plugin((const char*)param, selected_file.path) == PLUGIN_GOTO_WPS)
1131 return ONPLAY_START_PLAY; 1129 return ONPLAY_START_PLAY;
1132 1130
1133 return ONPLAY_RELOAD_DIR; 1131 return ONPLAY_RELOAD_DIR;
@@ -1253,15 +1251,15 @@ static int execute_hotkey(bool is_wps)
1253} 1251}
1254#endif /* HOTKEY */ 1252#endif /* HOTKEY */
1255 1253
1256int onplay(char* file, int attr, int from, bool hotkey) 1254int onplay(char* file, int attr, int from_context, bool hotkey)
1257{ 1255{
1258 const struct menu_item_ex *menu; 1256 const struct menu_item_ex *menu;
1259 onplay_result = ONPLAY_OK; 1257 onplay_result = ONPLAY_OK;
1260 context = from;
1261 ctx_current_playlist_insert = NULL; 1258 ctx_current_playlist_insert = NULL;
1262 selected_file = NULL; 1259 selected_file_set(from_context, NULL, attr);
1260
1263#ifdef HAVE_TAGCACHE 1261#ifdef HAVE_TAGCACHE
1264 if (context == CONTEXT_ID3DB && 1262 if (from_context == CONTEXT_ID3DB &&
1265 (attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) 1263 (attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO)
1266 { 1264 {
1267 ctx_add_to_playlist = tagtree_add_to_playlist; 1265 ctx_add_to_playlist = tagtree_add_to_playlist;
@@ -1269,8 +1267,8 @@ int onplay(char* file, int attr, int from, bool hotkey)
1269 { 1267 {
1270 /* add a leading slash so that catalog_add_to_a_playlist 1268 /* add a leading slash so that catalog_add_to_a_playlist
1271 later prefills the name when creating a new playlist */ 1269 later prefills the name when creating a new playlist */
1272 snprintf(selected_file_path, MAX_PATH, "/%s", file); 1270 snprintf(selected_file.buf, MAX_PATH, "/%s", file);
1273 selected_file = selected_file_path; 1271 selected_file.path = selected_file.buf;
1274 } 1272 }
1275 } 1273 }
1276 else 1274 else
@@ -1279,22 +1277,22 @@ int onplay(char* file, int attr, int from, bool hotkey)
1279 ctx_add_to_playlist = NULL; 1277 ctx_add_to_playlist = NULL;
1280 if (file != NULL) 1278 if (file != NULL)
1281 { 1279 {
1282 strmemccpy(selected_file_path, file, MAX_PATH); 1280 strmemccpy(selected_file.buf, file, MAX_PATH);
1283 selected_file = selected_file_path; 1281 selected_file.path = selected_file.buf;
1284 } 1282 }
1285 1283
1286 } 1284 }
1287 selected_file_attr = attr;
1288 int menu_selection; 1285 int menu_selection;
1286
1289#ifdef HAVE_HOTKEY 1287#ifdef HAVE_HOTKEY
1290 if (hotkey) 1288 if (hotkey)
1291 return execute_hotkey(context == CONTEXT_WPS); 1289 return execute_hotkey(from_context == CONTEXT_WPS);
1292#else 1290#else
1293 (void)hotkey; 1291 (void)hotkey;
1294#endif 1292#endif
1295 1293
1296 push_current_activity(ACTIVITY_CONTEXTMENU); 1294 push_current_activity(ACTIVITY_CONTEXTMENU);
1297 if (context == CONTEXT_WPS) 1295 if (from_context == CONTEXT_WPS)
1298 menu = &wps_onplay_menu; 1296 menu = &wps_onplay_menu;
1299 else 1297 else
1300 menu = &tree_onplay_menu; 1298 menu = &tree_onplay_menu;
@@ -1303,23 +1301,22 @@ int onplay(char* file, int attr, int from, bool hotkey)
1303 if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* Activity may have been */ 1301 if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* Activity may have been */
1304 pop_current_activity(); /* popped already by menu item */ 1302 pop_current_activity(); /* popped already by menu item */
1305 1303
1306 switch (menu_selection) 1304
1307 { 1305 if (menu_selection == GO_TO_WPS)
1308 case GO_TO_WPS: 1306 return ONPLAY_START_PLAY;
1309 return ONPLAY_START_PLAY; 1307 if (menu_selection == GO_TO_ROOT)
1310 case GO_TO_ROOT: 1308 return ONPLAY_MAINMENU;
1311 case GO_TO_MAINMENU: 1309 if (menu_selection == GO_TO_MAINMENU)
1312 return ONPLAY_MAINMENU; 1310 return ONPLAY_MAINMENU;
1313 case GO_TO_PLAYLIST_VIEWER: 1311 if (menu_selection == GO_TO_PLAYLIST_VIEWER)
1314 return ONPLAY_PLAYLIST; 1312 return ONPLAY_PLAYLIST;
1315 case GO_TO_PLUGIN: 1313 if (menu_selection == GO_TO_PLUGIN)
1316 return ONPLAY_PLUGIN; 1314 return ONPLAY_PLUGIN;
1317 default: 1315
1318 return onplay_result; 1316 return onplay_result;
1319 }
1320} 1317}
1321 1318
1322int get_onplay_context(void) 1319int get_onplay_context(void)
1323{ 1320{
1324 return context; 1321 return selected_file.context;
1325} 1322}
diff --git a/apps/onplay.h b/apps/onplay.h
index ea1c2e6c38..74dc045db3 100644
--- a/apps/onplay.h
+++ b/apps/onplay.h
@@ -25,7 +25,7 @@
25#include "menu.h" 25#include "menu.h"
26#endif 26#endif
27 27
28int onplay(char* file, int attr, int from_screen, bool hotkey); 28int onplay(char* file, int attr, int from_context, bool hotkey);
29int get_onplay_context(void); 29int get_onplay_context(void);
30 30
31enum { 31enum {