diff options
Diffstat (limited to 'apps/onplay.c')
-rw-r--r-- | apps/onplay.c | 995 |
1 files changed, 249 insertions, 746 deletions
diff --git a/apps/onplay.c b/apps/onplay.c index 572138e583..d468c0a545 100644 --- a/apps/onplay.c +++ b/apps/onplay.c | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | #include "debug.h" | 27 | #include "debug.h" |
28 | #include "lcd.h" | 28 | #include "lcd.h" |
29 | #include "file.h" | ||
30 | #include "audio.h" | 29 | #include "audio.h" |
31 | #include "menu.h" | 30 | #include "menu.h" |
32 | #include "lang.h" | 31 | #include "lang.h" |
@@ -43,6 +42,7 @@ | |||
43 | #include "talk.h" | 42 | #include "talk.h" |
44 | #include "onplay.h" | 43 | #include "onplay.h" |
45 | #include "filetypes.h" | 44 | #include "filetypes.h" |
45 | #include "fileop.h" | ||
46 | #include "open_plugin.h" | 46 | #include "open_plugin.h" |
47 | #include "plugin.h" | 47 | #include "plugin.h" |
48 | #include "bookmark.h" | 48 | #include "bookmark.h" |
@@ -65,12 +65,9 @@ | |||
65 | #include "shortcuts.h" | 65 | #include "shortcuts.h" |
66 | #include "misc.h" | 66 | #include "misc.h" |
67 | 67 | ||
68 | static int context; | ||
69 | static const char *selected_file = NULL; | ||
70 | static char selected_file_path[MAX_PATH]; | ||
71 | static int selected_file_attr = 0; | ||
72 | static int onplay_result = ONPLAY_OK; | 68 | static int onplay_result = ONPLAY_OK; |
73 | static bool in_queue_submenu = false; | 69 | static bool in_queue_submenu = false; |
70 | |||
74 | static bool (*ctx_current_playlist_insert)(int position, bool queue, bool create_new); | 71 | static bool (*ctx_current_playlist_insert)(int position, bool queue, bool create_new); |
75 | static int (*ctx_add_to_playlist)(const char* playlist, bool new_playlist); | 72 | static int (*ctx_add_to_playlist)(const char* playlist, bool new_playlist); |
76 | extern struct menu_item_ex file_menu; /* settings_menu.c */ | 73 | extern struct menu_item_ex file_menu; /* settings_menu.c */ |
@@ -84,30 +81,13 @@ 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 | ||
87 | /* Used for directory move, copy and delete */ | 84 | static struct selected_file |
88 | struct dirrecurse_params | ||
89 | { | ||
90 | char path[MAX_PATH]; /* Buffer for full path */ | ||
91 | size_t append; /* Append position in 'path' for stack push */ | ||
92 | }; | ||
93 | |||
94 | enum clipboard_op_flags | ||
95 | { | ||
96 | PASTE_CUT = 0x00, /* Is a move (cut) operation (default) */ | ||
97 | PASTE_COPY = 0x01, /* Is a copy operation */ | ||
98 | PASTE_OVERWRITE = 0x02, /* Overwrite destination */ | ||
99 | PASTE_EXDEV = 0x04, /* Actually copy/move across volumes */ | ||
100 | }; | ||
101 | |||
102 | /* result codec of various onplay operations */ | ||
103 | enum onplay_result_code | ||
104 | { | 85 | { |
105 | /* Anything < 0 is failure */ | 86 | char buf[MAX_PATH]; |
106 | OPRC_SUCCESS = 0, /* All operations completed successfully */ | 87 | const char *path; |
107 | OPRC_NOOP = 1, /* Operation didn't need to do anything */ | 88 | int attr; |
108 | OPRC_CANCELLED = 2, /* Operation was cancelled by user */ | 89 | int context; |
109 | OPRC_NOOVERWRT = 3, | 90 | } selected_file; |
110 | }; | ||
111 | 91 | ||
112 | static struct clipboard | 92 | static struct clipboard |
113 | { | 93 | { |
@@ -116,6 +96,14 @@ static struct clipboard | |||
116 | unsigned int flags; /* Operation type flags */ | 96 | unsigned int flags; /* Operation type flags */ |
117 | } clipboard; | 97 | } clipboard; |
118 | 98 | ||
99 | /* set selected file (doesn't touch buffer) */ | ||
100 | static 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 | |||
119 | /* Empty the clipboard */ | 107 | /* Empty the clipboard */ |
120 | static void clipboard_clear_selection(struct clipboard *clip) | 108 | static void clipboard_clear_selection(struct clipboard *clip) |
121 | { | 109 | { |
@@ -174,25 +162,21 @@ static int bookmark_menu_callback(int action, | |||
174 | struct gui_synclist *this_list) | 162 | struct gui_synclist *this_list) |
175 | { | 163 | { |
176 | (void) this_list; | 164 | (void) this_list; |
177 | switch (action) | 165 | if (action == ACTION_REQUEST_MENUITEM) |
178 | { | 166 | { |
179 | case ACTION_REQUEST_MENUITEM: | 167 | /* hide loading bookmarks menu if no bookmarks exist */ |
180 | /* hide loading bookmarks menu if no bookmarks exist */ | 168 | if (this_item == &bookmark_load_menu_item) |
181 | if (this_item == &bookmark_load_menu_item) | 169 | { |
182 | { | 170 | if (!bookmark_exists()) |
183 | if (!bookmark_exists()) | 171 | return ACTION_EXIT_MENUITEM; |
184 | return ACTION_EXIT_MENUITEM; | 172 | } |
185 | } | ||
186 | break; | ||
187 | case ACTION_EXIT_MENUITEM: | ||
188 | settings_save(); | ||
189 | break; | ||
190 | } | 173 | } |
174 | else if (action == ACTION_EXIT_MENUITEM) | ||
175 | settings_save(); | ||
176 | |||
191 | return action; | 177 | return action; |
192 | } | 178 | } |
193 | 179 | ||
194 | |||
195 | |||
196 | /* CONTEXT_WPS playlist options */ | 180 | /* CONTEXT_WPS playlist options */ |
197 | static bool shuffle_playlist(void) | 181 | static bool shuffle_playlist(void) |
198 | { | 182 | { |
@@ -244,46 +228,82 @@ MAKE_ONPLAYMENU( wps_playlist_menu, ID2P(LANG_CURRENT_PLAYLIST), | |||
244 | ); | 228 | ); |
245 | 229 | ||
246 | /* argument for add_to_playlist (for use by menu callbacks) */ | 230 | /* argument for add_to_playlist (for use by menu callbacks) */ |
231 | #define PL_NONE 0x00 | ||
232 | #define PL_QUEUE 0x01 | ||
233 | #define PL_REPLACE 0x02 | ||
247 | struct add_to_pl_param | 234 | struct add_to_pl_param |
248 | { | 235 | { |
249 | int8_t position; | 236 | int8_t position; |
250 | unsigned int queue: 1; | 237 | uint8_t flags; |
251 | unsigned int replace: 1; | ||
252 | }; | 238 | }; |
253 | 239 | ||
254 | static struct add_to_pl_param addtopl_insert = {PLAYLIST_INSERT, 0, 0}; | 240 | static struct add_to_pl_param addtopl_insert = {PLAYLIST_INSERT, PL_NONE}; |
255 | static struct add_to_pl_param addtopl_insert_first = {PLAYLIST_INSERT_FIRST, 0, 0}; | 241 | static struct add_to_pl_param addtopl_insert_first = {PLAYLIST_INSERT_FIRST, PL_NONE}; |
256 | static struct add_to_pl_param addtopl_insert_last = {PLAYLIST_INSERT_LAST, 0, 0}; | 242 | static struct add_to_pl_param addtopl_insert_last = {PLAYLIST_INSERT_LAST, PL_NONE}; |
257 | static struct add_to_pl_param addtopl_insert_shuf = {PLAYLIST_INSERT_SHUFFLED, 0, 0}; | 243 | static struct add_to_pl_param addtopl_insert_shuf = {PLAYLIST_INSERT_SHUFFLED, PL_NONE}; |
258 | static struct add_to_pl_param addtopl_insert_last_shuf = {PLAYLIST_INSERT_LAST_SHUFFLED, 0, 0}; | 244 | static struct add_to_pl_param addtopl_insert_last_shuf = {PLAYLIST_INSERT_LAST_SHUFFLED, PL_NONE}; |
245 | |||
246 | static struct add_to_pl_param addtopl_queue = {PLAYLIST_INSERT, PL_QUEUE}; | ||
247 | static struct add_to_pl_param addtopl_queue_first = {PLAYLIST_INSERT_FIRST, PL_QUEUE}; | ||
248 | static struct add_to_pl_param addtopl_queue_last = {PLAYLIST_INSERT_LAST, PL_QUEUE}; | ||
249 | static struct add_to_pl_param addtopl_queue_shuf = {PLAYLIST_INSERT_SHUFFLED, PL_QUEUE}; | ||
250 | static struct add_to_pl_param addtopl_queue_last_shuf = {PLAYLIST_INSERT_LAST_SHUFFLED, PL_QUEUE}; | ||
251 | |||
252 | static struct add_to_pl_param addtopl_replace = {PLAYLIST_INSERT, PL_REPLACE}; | ||
253 | static struct add_to_pl_param addtopl_replace_shuffled = {PLAYLIST_INSERT_LAST_SHUFFLED, PL_REPLACE}; | ||
254 | |||
255 | static void op_playlist_insert_selected(int position, bool queue) | ||
256 | { | ||
257 | #ifdef HAVE_TAGCACHE | ||
258 | if (selected_file.context == CONTEXT_STD && ctx_current_playlist_insert != NULL) | ||
259 | { | ||
260 | ctx_current_playlist_insert(position, queue, false); | ||
261 | return; | ||
262 | } | ||
263 | #endif | ||
264 | if ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) | ||
265 | playlist_insert_track(NULL, selected_file.path, position, queue, true); | ||
266 | else if ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_M3U) | ||
267 | playlist_insert_playlist(NULL, selected_file.path, position, queue); | ||
268 | else if (selected_file.attr & ATTR_DIRECTORY) | ||
269 | { | ||
270 | #ifdef HAVE_TAGCACHE | ||
271 | if (selected_file.context == CONTEXT_ID3DB) | ||
272 | { | ||
273 | tagtree_current_playlist_insert(position, queue); | ||
274 | return; | ||
275 | } | ||
276 | #endif | ||
277 | bool recurse = (global_settings.recursive_dir_insert == RECURSE_ON); | ||
278 | if (global_settings.recursive_dir_insert == RECURSE_ASK) | ||
279 | { | ||
259 | 280 | ||
260 | static struct add_to_pl_param addtopl_queue = {PLAYLIST_INSERT, 1, 0}; | 281 | const char *lines[] = { |
261 | static struct add_to_pl_param addtopl_queue_first = {PLAYLIST_INSERT_FIRST, 1, 0}; | 282 | ID2P(LANG_RECURSE_DIRECTORY_QUESTION), |
262 | static struct add_to_pl_param addtopl_queue_last = {PLAYLIST_INSERT_LAST, 1, 0}; | 283 | selected_file.path |
263 | static struct add_to_pl_param addtopl_queue_shuf = {PLAYLIST_INSERT_SHUFFLED, 1, 0}; | 284 | }; |
264 | static struct add_to_pl_param addtopl_queue_last_shuf = {PLAYLIST_INSERT_LAST_SHUFFLED, 1, 0}; | 285 | const struct text_message message={lines, 2}; |
286 | /* Ask if user wants to recurse directory */ | ||
287 | recurse = (gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES); | ||
288 | } | ||
265 | 289 | ||
266 | static struct add_to_pl_param addtopl_replace = {PLAYLIST_INSERT, 0, 1}; | 290 | playlist_insert_directory(NULL, selected_file.path, position, queue, |
267 | static struct add_to_pl_param addtopl_replace_shuffled = {PLAYLIST_INSERT_LAST_SHUFFLED, 0, 1}; | 291 | recurse == RECURSE_ON); |
292 | } | ||
293 | } | ||
268 | 294 | ||
269 | /* CONTEXT_[TREE|ID3DB|STD] playlist options */ | 295 | /* CONTEXT_[TREE|ID3DB|STD] playlist options */ |
270 | static int add_to_playlist(void* arg) | 296 | static int add_to_playlist(void* arg) |
271 | { | 297 | { |
272 | struct add_to_pl_param* param = arg; | 298 | struct add_to_pl_param* param = arg; |
273 | int position = param->position; | 299 | int position = param->position; |
274 | bool new_playlist = !!param->replace; | 300 | bool new_playlist = (param->flags & PL_REPLACE) == PL_REPLACE; |
275 | bool queue = !!param->queue; | 301 | bool queue = (param->flags & PL_QUEUE) == PL_QUEUE; |
276 | 302 | ||
277 | /* warn if replacing the playlist */ | 303 | /* warn if replacing the playlist */ |
278 | if (new_playlist && !warn_on_pl_erase()) | 304 | if (new_playlist && !warn_on_pl_erase()) |
279 | return 0; | 305 | return 0; |
280 | 306 | ||
281 | const char *lines[] = { | ||
282 | ID2P(LANG_RECURSE_DIRECTORY_QUESTION), | ||
283 | selected_file | ||
284 | }; | ||
285 | const struct text_message message={lines, 2}; | ||
286 | |||
287 | splash(0, ID2P(LANG_WAIT)); | 307 | splash(0, ID2P(LANG_WAIT)); |
288 | 308 | ||
289 | if (new_playlist && global_settings.keep_current_track_on_replace_playlist) | 309 | if (new_playlist && global_settings.keep_current_track_on_replace_playlist) |
@@ -307,38 +327,7 @@ static int add_to_playlist(void* arg) | |||
307 | playlist_set_last_shuffled_start(); | 327 | playlist_set_last_shuffled_start(); |
308 | } | 328 | } |
309 | 329 | ||
310 | #ifdef HAVE_TAGCACHE | 330 | op_playlist_insert_selected(position, queue); |
311 | if ((context == CONTEXT_ID3DB) && (selected_file_attr & ATTR_DIRECTORY)) | ||
312 | { | ||
313 | tagtree_current_playlist_insert(position, queue); | ||
314 | } | ||
315 | else if (context == CONTEXT_STD && ctx_current_playlist_insert != NULL) | ||
316 | { | ||
317 | ctx_current_playlist_insert(position, queue, false); | ||
318 | } | ||
319 | else | ||
320 | #endif | ||
321 | { | ||
322 | if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) | ||
323 | playlist_insert_track(NULL, selected_file, position, queue, true); | ||
324 | else if (selected_file_attr & ATTR_DIRECTORY) | ||
325 | { | ||
326 | bool recurse = false; | ||
327 | |||
328 | if (global_settings.recursive_dir_insert != RECURSE_ASK) | ||
329 | recurse = (bool)global_settings.recursive_dir_insert; | ||
330 | else | ||
331 | { | ||
332 | /* Ask if user wants to recurse directory */ | ||
333 | recurse = (gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES); | ||
334 | } | ||
335 | |||
336 | playlist_insert_directory(NULL, selected_file, position, queue, | ||
337 | recurse); | ||
338 | } | ||
339 | else if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U) | ||
340 | playlist_insert_playlist(NULL, selected_file, position, queue); | ||
341 | } | ||
342 | 331 | ||
343 | if (new_playlist && (playlist_amount() > 0)) | 332 | if (new_playlist && (playlist_amount() > 0)) |
344 | { | 333 | { |
@@ -358,7 +347,7 @@ static bool view_playlist(void) | |||
358 | { | 347 | { |
359 | bool result; | 348 | bool result; |
360 | 349 | ||
361 | result = playlist_viewer_ex(selected_file, NULL); | 350 | result = playlist_viewer_ex(selected_file.path, NULL); |
362 | 351 | ||
363 | if (result == PLAYLIST_VIEWER_OK && | 352 | if (result == PLAYLIST_VIEWER_OK && |
364 | onplay_result == ONPLAY_OK) | 353 | onplay_result == ONPLAY_OK) |
@@ -447,19 +436,22 @@ MAKE_ONPLAYMENU(tree_playlist_menu, ID2P(LANG_PLAYING_NEXT), | |||
447 | &replace_pl_item, | 436 | &replace_pl_item, |
448 | &replace_shuf_pl_item | 437 | &replace_shuf_pl_item |
449 | ); | 438 | ); |
439 | |||
450 | static int treeplaylist_callback(int action, | 440 | static int treeplaylist_callback(int action, |
451 | const struct menu_item_ex *this_item, | 441 | const struct menu_item_ex *this_item, |
452 | struct gui_synclist *this_list) | 442 | struct gui_synclist *this_list) |
453 | { | 443 | { |
454 | (void)this_list; | 444 | (void)this_list; |
445 | int sel_file_attr = (selected_file.attr & FILE_ATTR_MASK); | ||
446 | |||
455 | switch (action) | 447 | switch (action) |
456 | { | 448 | { |
457 | case ACTION_REQUEST_MENUITEM: | 449 | case ACTION_REQUEST_MENUITEM: |
458 | if (this_item == &tree_playlist_menu) | 450 | if (this_item == &tree_playlist_menu) |
459 | { | 451 | { |
460 | if ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO && | 452 | if (sel_file_attr != FILE_ATTR_AUDIO && |
461 | (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_M3U && | 453 | sel_file_attr != FILE_ATTR_M3U && |
462 | (selected_file_attr & ATTR_DIRECTORY) == 0) | 454 | (selected_file.attr & ATTR_DIRECTORY) == 0) |
463 | return ACTION_EXIT_MENUITEM; | 455 | return ACTION_EXIT_MENUITEM; |
464 | } | 456 | } |
465 | else if (this_item == &queue_menu) | 457 | else if (this_item == &queue_menu) |
@@ -476,7 +468,7 @@ static int treeplaylist_callback(int action, | |||
476 | { | 468 | { |
477 | struct add_to_pl_param *param = this_item->function_param->param; | 469 | struct add_to_pl_param *param = this_item->function_param->param; |
478 | 470 | ||
479 | if (param->queue) | 471 | if ((param->flags & PL_QUEUE) == PL_QUEUE) |
480 | { | 472 | { |
481 | if (global_settings.show_queue_options != QUEUE_SHOW_AT_TOPLEVEL && | 473 | if (global_settings.show_queue_options != QUEUE_SHOW_AT_TOPLEVEL && |
482 | !in_queue_submenu) | 474 | !in_queue_submenu) |
@@ -489,12 +481,12 @@ static int treeplaylist_callback(int action, | |||
489 | if (!global_settings.show_shuffled_adding_options) | 481 | if (!global_settings.show_shuffled_adding_options) |
490 | return ACTION_EXIT_MENUITEM; | 482 | return ACTION_EXIT_MENUITEM; |
491 | 483 | ||
492 | if ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_M3U && | 484 | if (sel_file_attr != FILE_ATTR_M3U && |
493 | (selected_file_attr & ATTR_DIRECTORY) == 0) | 485 | (selected_file.attr & ATTR_DIRECTORY) == 0) |
494 | return ACTION_EXIT_MENUITEM; | 486 | return ACTION_EXIT_MENUITEM; |
495 | } | 487 | } |
496 | 488 | ||
497 | if (!param->replace) | 489 | if ((param->flags & PL_REPLACE) != PL_REPLACE) |
498 | { | 490 | { |
499 | if (!(audio_status() & AUDIO_STATUS_PLAY)) | 491 | if (!(audio_status() & AUDIO_STATUS_PLAY)) |
500 | return ACTION_EXIT_MENUITEM; | 492 | return ACTION_EXIT_MENUITEM; |
@@ -513,10 +505,8 @@ static int treeplaylist_callback(int action, | |||
513 | 505 | ||
514 | void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_insert_cb)) | 506 | void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_insert_cb)) |
515 | { | 507 | { |
516 | context = CONTEXT_STD; | ||
517 | ctx_current_playlist_insert = playlist_insert_cb; | 508 | ctx_current_playlist_insert = playlist_insert_cb; |
518 | selected_file = path; | 509 | selected_file_set(CONTEXT_STD, path, attr); |
519 | selected_file_attr = attr; | ||
520 | in_queue_submenu = false; | 510 | in_queue_submenu = false; |
521 | do_menu(&tree_playlist_menu, NULL, NULL, false); | 511 | do_menu(&tree_playlist_menu, NULL, NULL, false); |
522 | } | 512 | } |
@@ -524,13 +514,13 @@ void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_inser | |||
524 | /* playlist catalog options */ | 514 | /* playlist catalog options */ |
525 | static bool cat_add_to_a_playlist(void) | 515 | static bool cat_add_to_a_playlist(void) |
526 | { | 516 | { |
527 | return catalog_add_to_a_playlist(selected_file, selected_file_attr, | 517 | return catalog_add_to_a_playlist(selected_file.path, selected_file.attr, |
528 | false, NULL, ctx_add_to_playlist); | 518 | false, NULL, ctx_add_to_playlist); |
529 | } | 519 | } |
530 | 520 | ||
531 | static bool cat_add_to_a_new_playlist(void) | 521 | static bool cat_add_to_a_new_playlist(void) |
532 | { | 522 | { |
533 | return catalog_add_to_a_playlist(selected_file, selected_file_attr, | 523 | return catalog_add_to_a_playlist(selected_file.path, selected_file.attr, |
534 | true, NULL, ctx_add_to_playlist); | 524 | true, NULL, ctx_add_to_playlist); |
535 | } | 525 | } |
536 | 526 | ||
@@ -548,10 +538,8 @@ MAKE_ONPLAYMENU(cat_playlist_menu, ID2P(LANG_ADD_TO_PL), | |||
548 | 538 | ||
549 | void onplay_show_playlist_cat_menu(const char* track_name, int attr, void (*add_to_pl_cb)) | 539 | void onplay_show_playlist_cat_menu(const char* track_name, int attr, void (*add_to_pl_cb)) |
550 | { | 540 | { |
551 | context = CONTEXT_STD; | ||
552 | ctx_add_to_playlist = add_to_pl_cb; | 541 | ctx_add_to_playlist = add_to_pl_cb; |
553 | selected_file = track_name; | 542 | selected_file_set(CONTEXT_STD, track_name, attr); |
554 | selected_file_attr = attr; | ||
555 | do_menu(&cat_playlist_menu, NULL, NULL, false); | 543 | do_menu(&cat_playlist_menu, NULL, NULL, false); |
556 | } | 544 | } |
557 | 545 | ||
@@ -561,515 +549,48 @@ static int cat_playlist_callback(int action, | |||
561 | { | 549 | { |
562 | (void)this_item; | 550 | (void)this_item; |
563 | (void)this_list; | 551 | (void)this_list; |
564 | if (!selected_file || | 552 | if (!selected_file.path || |
565 | (((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) && | 553 | (((selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) && |
566 | ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) && | 554 | ((selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) && |
567 | ((selected_file_attr & ATTR_DIRECTORY) == 0))) | 555 | ((selected_file.attr & ATTR_DIRECTORY) == 0))) |
568 | { | 556 | { |
569 | return ACTION_EXIT_MENUITEM; | 557 | return ACTION_EXIT_MENUITEM; |
570 | } | 558 | } |
571 | 559 | ||
572 | switch (action) | 560 | if (action == ACTION_REQUEST_MENUITEM) |
573 | { | ||
574 | case ACTION_REQUEST_MENUITEM: | ||
575 | if ((audio_status() & AUDIO_STATUS_PLAY) || context != CONTEXT_WPS) | ||
576 | { | ||
577 | return action; | ||
578 | } | ||
579 | else | ||
580 | return ACTION_EXIT_MENUITEM; | ||
581 | break; | ||
582 | } | ||
583 | return action; | ||
584 | } | ||
585 | |||
586 | static void draw_slider(void) | ||
587 | { | ||
588 | struct viewport *last_vp; | ||
589 | FOR_NB_SCREENS(i) | ||
590 | { | ||
591 | struct viewport vp; | ||
592 | int slider_height = 2*screens[i].getcharheight(); | ||
593 | viewport_set_defaults(&vp, i); | ||
594 | last_vp = screens[i].set_viewport(&vp); | ||
595 | show_busy_slider(&screens[i], 1, vp.height - slider_height, | ||
596 | vp.width-2, slider_height-1); | ||
597 | screens[i].update_viewport(); | ||
598 | screens[i].set_viewport(last_vp); | ||
599 | } | ||
600 | } | ||
601 | |||
602 | static void clear_display(bool update) | ||
603 | { | ||
604 | struct viewport vp; | ||
605 | struct viewport *last_vp; | ||
606 | FOR_NB_SCREENS(i) | ||
607 | { | 561 | { |
608 | struct screen * screen = &screens[i]; | 562 | if ((audio_status() & AUDIO_STATUS_PLAY) |
609 | viewport_set_defaults(&vp, screen->screen_type); | 563 | || selected_file.context != CONTEXT_WPS) |
610 | last_vp = screen->set_viewport(&vp); | 564 | { |
611 | screen->clear_viewport(); | 565 | return action; |
612 | if (update) { | ||
613 | screen->update_viewport(); | ||
614 | } | 566 | } |
615 | screen->set_viewport(last_vp); | 567 | return ACTION_EXIT_MENUITEM; |
616 | } | 568 | } |
617 | } | 569 | return action; |
618 | |||
619 | static void splash_path(const char *path) | ||
620 | { | ||
621 | clear_display(false); | ||
622 | path_basename(path, &path); | ||
623 | splash(0, path); | ||
624 | draw_slider(); | ||
625 | } | ||
626 | |||
627 | /* Splashes the path and checks the keys */ | ||
628 | static bool poll_cancel_action(const char *path) | ||
629 | { | ||
630 | splash_path(path); | ||
631 | return ACTION_STD_CANCEL == get_action(CONTEXT_STD, TIMEOUT_NOBLOCK); | ||
632 | } | ||
633 | |||
634 | static bool check_new_name(const char *basename) | ||
635 | { | ||
636 | /* at least prevent escapes out of the base directory from keyboard- | ||
637 | entered filenames; the file code should reject other invalidities */ | ||
638 | return *basename != '\0' && !strchr(basename, PATH_SEPCH) && | ||
639 | !is_dotdir_name(basename); | ||
640 | } | 570 | } |
641 | 571 | ||
642 | static void splash_cancelled(void) | 572 | static void splash_cancelled(void) |
643 | { | 573 | { |
644 | clear_display(true); | 574 | clear_screen_buffer(true); |
645 | splash(HZ, ID2P(LANG_CANCEL)); | 575 | splash(HZ, ID2P(LANG_CANCEL)); |
646 | } | 576 | } |
647 | 577 | ||
648 | static void splash_failed(int lang_what) | 578 | static void splash_failed(int lang_what, int err) |
649 | { | 579 | { |
650 | cond_talk_ids_fq(lang_what, LANG_FAILED); | 580 | cond_talk_ids_fq(lang_what, LANG_FAILED); |
651 | clear_display(true); | 581 | clear_screen_buffer(true); |
652 | splashf(HZ*2, "%s %s", str(lang_what), str(LANG_FAILED)); | 582 | splashf(HZ*2, "%s %s (%d)", str(lang_what), str(LANG_FAILED), err); |
653 | } | ||
654 | |||
655 | /* helper function to remove a non-empty directory */ | ||
656 | static int remove_dir(struct dirrecurse_params *parm) | ||
657 | { | ||
658 | DIR *dir = opendir(parm->path); | ||
659 | if (!dir) { | ||
660 | return -1; /* open error */ | ||
661 | } | ||
662 | |||
663 | size_t append = parm->append; | ||
664 | int rc = OPRC_SUCCESS; | ||
665 | |||
666 | /* walk through the directory content */ | ||
667 | while (rc == OPRC_SUCCESS) { | ||
668 | errno = 0; /* distinguish failure from eod */ | ||
669 | struct dirent *entry = readdir(dir); | ||
670 | if (!entry) { | ||
671 | if (errno) { | ||
672 | rc = -1; | ||
673 | } | ||
674 | break; | ||
675 | } | ||
676 | |||
677 | struct dirinfo info = dir_get_info(dir, entry); | ||
678 | if ((info.attribute & ATTR_DIRECTORY) && | ||
679 | is_dotdir_name(entry->d_name)) { | ||
680 | continue; /* skip these */ | ||
681 | } | ||
682 | |||
683 | /* append name to current directory */ | ||
684 | parm->append = append + path_append(&parm->path[append], | ||
685 | PA_SEP_HARD, entry->d_name, | ||
686 | sizeof (parm->path) - append); | ||
687 | if (parm->append >= sizeof (parm->path)) { | ||
688 | rc = -1; | ||
689 | break; /* no space left in buffer */ | ||
690 | } | ||
691 | |||
692 | if (info.attribute & ATTR_DIRECTORY) { | ||
693 | /* remove a subdirectory */ | ||
694 | rc = remove_dir(parm); | ||
695 | } else { | ||
696 | /* remove a file */ | ||
697 | if (poll_cancel_action(parm->path)) { | ||
698 | rc = OPRC_CANCELLED; | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | rc = remove(parm->path); | ||
703 | } | ||
704 | |||
705 | /* Remove basename we added above */ | ||
706 | parm->path[append] = '\0'; | ||
707 | } | ||
708 | |||
709 | closedir(dir); | ||
710 | |||
711 | if (rc == 0) { | ||
712 | /* remove the now empty directory */ | ||
713 | if (poll_cancel_action(parm->path)) { | ||
714 | rc = OPRC_CANCELLED; | ||
715 | } else { | ||
716 | rc = rmdir(parm->path); | ||
717 | } | ||
718 | } | ||
719 | |||
720 | return rc; | ||
721 | } | ||
722 | |||
723 | /* share code for file and directory deletion, saves space */ | ||
724 | static int delete_file_dir(void) | ||
725 | { | ||
726 | const char *to_delete=selected_file; | ||
727 | const int to_delete_attr=selected_file_attr; | ||
728 | if (confirm_delete_yesno(to_delete) != YESNO_YES) { | ||
729 | return 1; | ||
730 | } | ||
731 | |||
732 | clear_display(true); | ||
733 | splash(HZ/2, ID2P(LANG_DELETING)); | ||
734 | |||
735 | int rc = -1; | ||
736 | |||
737 | if (to_delete_attr & ATTR_DIRECTORY) { /* true if directory */ | ||
738 | struct dirrecurse_params parm; | ||
739 | parm.append = strlcpy(parm.path, to_delete, sizeof (parm.path)); | ||
740 | |||
741 | if (parm.append < sizeof (parm.path)) { | ||
742 | cpu_boost(true); | ||
743 | rc = remove_dir(&parm); | ||
744 | cpu_boost(false); | ||
745 | } | ||
746 | } else { | ||
747 | rc = remove(to_delete); | ||
748 | } | ||
749 | |||
750 | if (rc < OPRC_SUCCESS) { | ||
751 | splash_failed(LANG_DELETE); | ||
752 | } else if (rc == OPRC_CANCELLED) { | ||
753 | splash_cancelled(); | ||
754 | } | ||
755 | |||
756 | if (rc != OPRC_NOOP) { | ||
757 | /* Could have failed after some but not all needed changes; reload */ | ||
758 | onplay_result = ONPLAY_RELOAD_DIR; | ||
759 | } | ||
760 | |||
761 | return 1; | ||
762 | } | ||
763 | |||
764 | static int rename_file(void) | ||
765 | { | ||
766 | int rc = -1; | ||
767 | char newname[MAX_PATH]; | ||
768 | const char *oldbase, *selection = selected_file; | ||
769 | |||
770 | path_basename(selection, &oldbase); | ||
771 | size_t pathlen = oldbase - selection; | ||
772 | char *newbase = newname + pathlen; | ||
773 | |||
774 | if (strmemccpy(newname, selection, sizeof (newname)) == NULL) { | ||
775 | /* Too long */ | ||
776 | } else if (kbd_input(newbase, sizeof (newname) - pathlen, NULL) < 0) { | ||
777 | rc = OPRC_CANCELLED; | ||
778 | } else if (!strcmp(oldbase, newbase)) { | ||
779 | rc = OPRC_NOOP; /* No change at all */ | ||
780 | } else if (check_new_name(newbase)) { | ||
781 | switch (relate(selection, newname)) | ||
782 | { | ||
783 | case RELATE_DIFFERENT: | ||
784 | if (file_exists(newname)) { | ||
785 | break; /* don't overwrite */ | ||
786 | } | ||
787 | /* Fall-through */ | ||
788 | case RELATE_SAME: | ||
789 | rc = rename(selection, newname); | ||
790 | break; | ||
791 | case RELATE_PREFIX: | ||
792 | default: | ||
793 | break; | ||
794 | } | ||
795 | } | ||
796 | |||
797 | if (rc < OPRC_SUCCESS) { | ||
798 | splash_failed(LANG_RENAME); | ||
799 | } else if (rc == OPRC_CANCELLED) { | ||
800 | /* splash_cancelled(); kbd_input() splashes it */ | ||
801 | } else if (rc == OPRC_SUCCESS) { | ||
802 | onplay_result = ONPLAY_RELOAD_DIR; | ||
803 | } | ||
804 | |||
805 | return 1; | ||
806 | } | ||
807 | |||
808 | static int create_dir(void) | ||
809 | { | ||
810 | int rc = -1; | ||
811 | char dirname[MAX_PATH]; | ||
812 | size_t pathlen = path_append(dirname, getcwd(NULL, 0), PA_SEP_HARD, | ||
813 | sizeof (dirname)); | ||
814 | char *basename = dirname + pathlen; | ||
815 | |||
816 | if (pathlen >= sizeof (dirname)) { | ||
817 | /* Too long */ | ||
818 | } else if (kbd_input(basename, sizeof (dirname) - pathlen, NULL) < 0) { | ||
819 | rc = OPRC_CANCELLED; | ||
820 | } else if (check_new_name(basename)) { | ||
821 | rc = mkdir(dirname); | ||
822 | } | ||
823 | |||
824 | if (rc < OPRC_SUCCESS) { | ||
825 | splash_failed(LANG_CREATE_DIR); | ||
826 | } else if (rc == OPRC_CANCELLED) { | ||
827 | /* splash_cancelled(); kbd_input() splashes it */ | ||
828 | } else if (rc == OPRC_SUCCESS) { | ||
829 | onplay_result = ONPLAY_RELOAD_DIR; | ||
830 | } | ||
831 | |||
832 | return 1; | ||
833 | } | ||
834 | |||
835 | /* Paste a file */ | ||
836 | static int clipboard_pastefile(const char *src, const char *target, | ||
837 | unsigned int flags) | ||
838 | { | ||
839 | int rc = -1; | ||
840 | |||
841 | while (!(flags & (PASTE_COPY | PASTE_EXDEV))) { | ||
842 | if ((flags & PASTE_OVERWRITE) || !file_exists(target)) { | ||
843 | /* Rename and possibly overwrite the file */ | ||
844 | if (poll_cancel_action(src)) { | ||
845 | rc = OPRC_CANCELLED; | ||
846 | } else { | ||
847 | rc = rename(src, target); | ||
848 | } | ||
849 | |||
850 | #ifdef HAVE_MULTIVOLUME | ||
851 | if (rc < 0 && errno == EXDEV) { | ||
852 | /* Failed because cross volume rename doesn't work; force | ||
853 | a move instead */ | ||
854 | flags |= PASTE_EXDEV; | ||
855 | break; | ||
856 | } | ||
857 | #endif /* HAVE_MULTIVOLUME */ | ||
858 | } | ||
859 | |||
860 | return rc; | ||
861 | } | ||
862 | |||
863 | /* See if we can get the plugin buffer for the file copy buffer */ | ||
864 | size_t buffersize; | ||
865 | char *buffer = (char *) plugin_get_buffer(&buffersize); | ||
866 | if (buffer == NULL || buffersize < 512) { | ||
867 | /* Not large enough, try for a disk sector worth of stack | ||
868 | instead */ | ||
869 | buffersize = 512; | ||
870 | buffer = (char *)alloca(buffersize); | ||
871 | } | ||
872 | |||
873 | if (buffer == NULL) { | ||
874 | return -1; | ||
875 | } | ||
876 | |||
877 | buffersize &= ~0x1ff; /* Round buffer size to multiple of sector | ||
878 | size */ | ||
879 | |||
880 | int src_fd = open(src, O_RDONLY); | ||
881 | if (src_fd >= 0) { | ||
882 | int oflag = O_WRONLY|O_CREAT; | ||
883 | |||
884 | if (!(flags & PASTE_OVERWRITE)) { | ||
885 | oflag |= O_EXCL; | ||
886 | } | ||
887 | |||
888 | int target_fd = open(target, oflag, 0666); | ||
889 | if (target_fd >= 0) { | ||
890 | off_t total_size = 0; | ||
891 | off_t next_cancel_test = 0; /* No excessive button polling */ | ||
892 | |||
893 | rc = OPRC_SUCCESS; | ||
894 | |||
895 | while (rc == OPRC_SUCCESS) { | ||
896 | if (total_size >= next_cancel_test) { | ||
897 | next_cancel_test = total_size + 0x10000; | ||
898 | if (poll_cancel_action(src)) { | ||
899 | rc = OPRC_CANCELLED; | ||
900 | break; | ||
901 | } | ||
902 | } | ||
903 | |||
904 | ssize_t bytesread = read(src_fd, buffer, buffersize); | ||
905 | if (bytesread <= 0) { | ||
906 | if (bytesread < 0) { | ||
907 | rc = -1; | ||
908 | } | ||
909 | /* else eof on buffer boundary; nothing to write */ | ||
910 | break; | ||
911 | } | ||
912 | |||
913 | ssize_t byteswritten = write(target_fd, buffer, bytesread); | ||
914 | if (byteswritten < bytesread) { | ||
915 | /* Some I/O error */ | ||
916 | rc = -1; | ||
917 | break; | ||
918 | } | ||
919 | |||
920 | total_size += byteswritten; | ||
921 | |||
922 | if (bytesread < (ssize_t)buffersize) { | ||
923 | /* EOF with trailing bytes */ | ||
924 | break; | ||
925 | } | ||
926 | } | ||
927 | |||
928 | if (rc == OPRC_SUCCESS) { | ||
929 | /* If overwriting, set the correct length if original was | ||
930 | longer */ | ||
931 | rc = ftruncate(target_fd, total_size); | ||
932 | } | ||
933 | |||
934 | close(target_fd); | ||
935 | |||
936 | if (rc != OPRC_SUCCESS) { | ||
937 | /* Copy failed. Cleanup. */ | ||
938 | remove(target); | ||
939 | } | ||
940 | } | ||
941 | |||
942 | close(src_fd); | ||
943 | } | ||
944 | |||
945 | if (rc == OPRC_SUCCESS && !(flags & PASTE_COPY)) { | ||
946 | /* Remove the source file */ | ||
947 | rc = remove(src); | ||
948 | } | ||
949 | |||
950 | return rc; | ||
951 | } | ||
952 | |||
953 | /* Paste a directory */ | ||
954 | static int clipboard_pastedirectory(struct dirrecurse_params *src, | ||
955 | struct dirrecurse_params *target, | ||
956 | unsigned int flags) | ||
957 | { | ||
958 | int rc = -1; | ||
959 | |||
960 | while (!(flags & (PASTE_COPY | PASTE_EXDEV))) { | ||
961 | if ((flags & PASTE_OVERWRITE) || !file_exists(target->path)) { | ||
962 | /* Just try to move the directory */ | ||
963 | if (poll_cancel_action(src->path)) { | ||
964 | rc = OPRC_CANCELLED; | ||
965 | } else { | ||
966 | rc = rename(src->path, target->path); | ||
967 | } | ||
968 | |||
969 | if (rc < 0) { | ||
970 | int errnum = errno; | ||
971 | if (errnum == ENOTEMPTY && (flags & PASTE_OVERWRITE)) { | ||
972 | /* Directory is not empty thus rename() will not do a quick | ||
973 | overwrite */ | ||
974 | break; | ||
975 | } | ||
976 | #ifdef HAVE_MULTIVOLUME | ||
977 | else if (errnum == EXDEV) { | ||
978 | /* Failed because cross volume rename doesn't work; force | ||
979 | a move instead */ | ||
980 | flags |= PASTE_EXDEV; | ||
981 | break; | ||
982 | } | ||
983 | #endif /* HAVE_MULTIVOLUME */ | ||
984 | } | ||
985 | } | ||
986 | |||
987 | return rc; | ||
988 | } | ||
989 | |||
990 | DIR *srcdir = opendir(src->path); | ||
991 | |||
992 | if (srcdir) { | ||
993 | /* Make a directory to copy things to */ | ||
994 | rc = mkdir(target->path); | ||
995 | if (rc < 0 && errno == EEXIST && (flags & PASTE_OVERWRITE)) { | ||
996 | /* Exists and overwrite was approved */ | ||
997 | rc = OPRC_SUCCESS; | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | size_t srcap = src->append, targetap = target->append; | ||
1002 | |||
1003 | /* Walk through the directory content; this loop will exit as soon as | ||
1004 | there's a problem */ | ||
1005 | while (rc == OPRC_SUCCESS) { | ||
1006 | errno = 0; /* Distinguish failure from eod */ | ||
1007 | struct dirent *entry = readdir(srcdir); | ||
1008 | if (!entry) { | ||
1009 | if (errno) { | ||
1010 | rc = -1; | ||
1011 | } | ||
1012 | break; | ||
1013 | } | ||
1014 | |||
1015 | struct dirinfo info = dir_get_info(srcdir, entry); | ||
1016 | if ((info.attribute & ATTR_DIRECTORY) && | ||
1017 | is_dotdir_name(entry->d_name)) { | ||
1018 | continue; /* Skip these */ | ||
1019 | } | ||
1020 | |||
1021 | /* Append names to current directories */ | ||
1022 | src->append = srcap + | ||
1023 | path_append(&src->path[srcap], PA_SEP_HARD, entry->d_name, | ||
1024 | sizeof(src->path) - srcap); | ||
1025 | |||
1026 | target->append = targetap + | ||
1027 | path_append(&target->path[targetap], PA_SEP_HARD, entry->d_name, | ||
1028 | sizeof (target->path) - targetap); | ||
1029 | |||
1030 | if (src->append >= sizeof (src->path) || | ||
1031 | target->append >= sizeof (target->path)) { | ||
1032 | rc = -1; /* No space left in buffer */ | ||
1033 | break; | ||
1034 | } | ||
1035 | |||
1036 | if (poll_cancel_action(src->path)) { | ||
1037 | rc = OPRC_CANCELLED; | ||
1038 | break; | ||
1039 | } | ||
1040 | |||
1041 | DEBUGF("Copy %s to %s\n", src->path, target->path); | ||
1042 | |||
1043 | if (info.attribute & ATTR_DIRECTORY) { | ||
1044 | /* Copy/move a subdirectory */ | ||
1045 | rc = clipboard_pastedirectory(src, target, flags); /* recursion */ | ||
1046 | } else { | ||
1047 | /* Copy/move a file */ | ||
1048 | rc = clipboard_pastefile(src->path, target->path, flags); | ||
1049 | } | ||
1050 | |||
1051 | /* Remove basenames we added above */ | ||
1052 | src->path[srcap] = target->path[targetap] = '\0'; | ||
1053 | } | ||
1054 | |||
1055 | if (rc == OPRC_SUCCESS && !(flags & PASTE_COPY)) { | ||
1056 | /* Remove the now empty directory */ | ||
1057 | rc = rmdir(src->path); | ||
1058 | } | ||
1059 | |||
1060 | closedir(srcdir); | ||
1061 | return rc; | ||
1062 | } | 583 | } |
1063 | 584 | ||
1064 | static bool clipboard_cut(void) | 585 | static bool clipboard_cut(void) |
1065 | { | 586 | { |
1066 | return clipboard_clip(&clipboard, selected_file, selected_file_attr, | 587 | return clipboard_clip(&clipboard, selected_file.path, selected_file.attr, |
1067 | PASTE_CUT); | 588 | PASTE_CUT); |
1068 | } | 589 | } |
1069 | 590 | ||
1070 | static bool clipboard_copy(void) | 591 | static bool clipboard_copy(void) |
1071 | { | 592 | { |
1072 | return clipboard_clip(&clipboard, selected_file, selected_file_attr, | 593 | return clipboard_clip(&clipboard, selected_file.path, selected_file.attr, |
1073 | PASTE_COPY); | 594 | PASTE_COPY); |
1074 | } | 595 | } |
1075 | 596 | ||
@@ -1079,82 +600,24 @@ static int clipboard_paste(void) | |||
1079 | if (!clipboard.path[0]) | 600 | if (!clipboard.path[0]) |
1080 | return 1; | 601 | return 1; |
1081 | 602 | ||
1082 | int rc = -1; | 603 | int rc = copy_move_fileobject(clipboard.path, getcwd(NULL, 0), clipboard.flags); |
1083 | |||
1084 | struct dirrecurse_params src, target; | ||
1085 | unsigned int flags = clipboard.flags; | ||
1086 | |||
1087 | /* Figure out the name of the selection */ | ||
1088 | const char *nameptr; | ||
1089 | path_basename(clipboard.path, &nameptr); | ||
1090 | |||
1091 | /* Final target is current directory plus name of selection */ | ||
1092 | target.append = path_append(target.path, getcwd(NULL, 0), | ||
1093 | nameptr, sizeof (target.path)); | ||
1094 | |||
1095 | switch (target.append < sizeof (target.path) ? | ||
1096 | relate(clipboard.path, target.path) : -1) | ||
1097 | { | ||
1098 | case RELATE_SAME: | ||
1099 | rc = OPRC_NOOP; | ||
1100 | break; | ||
1101 | |||
1102 | case RELATE_DIFFERENT: | ||
1103 | if (file_exists(target.path)) { | ||
1104 | /* If user chooses not to overwrite, cancel */ | ||
1105 | if (confirm_overwrite_yesno() == YESNO_NO) { | ||
1106 | rc = OPRC_NOOVERWRT; | ||
1107 | break; | ||
1108 | } | ||
1109 | |||
1110 | flags |= PASTE_OVERWRITE; | ||
1111 | } | ||
1112 | |||
1113 | clear_display(true); | ||
1114 | splash(HZ/2, (flags & PASTE_COPY) ? ID2P(LANG_COPYING) : | ||
1115 | ID2P(LANG_MOVING)); | ||
1116 | |||
1117 | /* Now figure out what we're doing */ | ||
1118 | cpu_boost(true); | ||
1119 | |||
1120 | if (clipboard.attr & ATTR_DIRECTORY) { | ||
1121 | /* Copy or move a subdirectory */ | ||
1122 | src.append = strlcpy(src.path, clipboard.path, | ||
1123 | sizeof (src.path)); | ||
1124 | if (src.append < sizeof (src.path)) { | ||
1125 | rc = clipboard_pastedirectory(&src, &target, flags); | ||
1126 | } | ||
1127 | } else { | ||
1128 | /* Copy or move a file */ | ||
1129 | rc = clipboard_pastefile(clipboard.path, target.path, flags); | ||
1130 | } | ||
1131 | |||
1132 | cpu_boost(false); | ||
1133 | break; | ||
1134 | |||
1135 | case RELATE_PREFIX: | ||
1136 | default: /* Some other relation / failure */ | ||
1137 | break; | ||
1138 | } | ||
1139 | |||
1140 | clear_display(true); | ||
1141 | 604 | ||
1142 | switch (rc) | 605 | switch (rc) |
1143 | { | 606 | { |
1144 | case OPRC_CANCELLED: | 607 | case FORC_CANCELLED: |
1145 | splash_cancelled(); | 608 | splash_cancelled(); |
1146 | /* Fallthrough */ | 609 | /* Fallthrough */ |
1147 | case OPRC_SUCCESS: | 610 | case FORC_SUCCESS: |
1148 | onplay_result = ONPLAY_RELOAD_DIR; | 611 | onplay_result = ONPLAY_RELOAD_DIR; |
1149 | /* Fallthrough */ | 612 | /* Fallthrough */ |
1150 | case OPRC_NOOP: | 613 | case FORC_NOOP: |
1151 | clipboard_clear_selection(&clipboard); | 614 | clipboard_clear_selection(&clipboard); |
1152 | /* Fallthrough */ | 615 | /* Fallthrough */ |
1153 | case OPRC_NOOVERWRT: | 616 | case FORC_NOOVERWRT: |
1154 | break; | 617 | break; |
1155 | default: | 618 | default: |
1156 | if (rc < OPRC_SUCCESS) { | 619 | if (rc < FORC_SUCCESS) { |
1157 | splash_failed(LANG_PASTE); | 620 | splash_failed(LANG_PASTE, rc); |
1158 | onplay_result = ONPLAY_RELOAD_DIR; | 621 | onplay_result = ONPLAY_RELOAD_DIR; |
1159 | } | 622 | } |
1160 | } | 623 | } |
@@ -1182,13 +645,10 @@ static int ratingitem_callback(int action, | |||
1182 | { | 645 | { |
1183 | (void)this_item; | 646 | (void)this_item; |
1184 | (void)this_list; | 647 | (void)this_list; |
1185 | switch (action) | 648 | if (action == ACTION_REQUEST_MENUITEM) |
1186 | { | 649 | { |
1187 | case ACTION_REQUEST_MENUITEM: | 650 | if (!selected_file.path || !global_settings.runtimedb || !tagcache_is_usable()) |
1188 | if (!selected_file || !global_settings.runtimedb || | 651 | return ACTION_EXIT_MENUITEM; |
1189 | !tagcache_is_usable()) | ||
1190 | return ACTION_EXIT_MENUITEM; | ||
1191 | break; | ||
1192 | } | 652 | } |
1193 | return action; | 653 | return action; |
1194 | } | 654 | } |
@@ -1215,13 +675,10 @@ static int view_cue_item_callback(int action, | |||
1215 | (void)this_item; | 675 | (void)this_item; |
1216 | (void)this_list; | 676 | (void)this_list; |
1217 | struct mp3entry* id3 = audio_current_track(); | 677 | struct mp3entry* id3 = audio_current_track(); |
1218 | switch (action) | 678 | if (action == ACTION_REQUEST_MENUITEM) |
1219 | { | 679 | { |
1220 | case ACTION_REQUEST_MENUITEM: | 680 | if (!selected_file.path || !id3 || !id3->cuesheet) |
1221 | if (!selected_file | 681 | return ACTION_EXIT_MENUITEM; |
1222 | || !id3 || !id3->cuesheet) | ||
1223 | return ACTION_EXIT_MENUITEM; | ||
1224 | break; | ||
1225 | } | 682 | } |
1226 | return action; | 683 | return action; |
1227 | } | 684 | } |
@@ -1249,13 +706,57 @@ MENUITEM_FUNCTION(pitch_screen_item, 0, ID2P(LANG_PITCH), | |||
1249 | gui_syncpitchscreen_run, NULL, Icon_Audio); | 706 | gui_syncpitchscreen_run, NULL, Icon_Audio); |
1250 | #endif | 707 | #endif |
1251 | 708 | ||
709 | static int clipboard_delete_selected_fileobject(void) | ||
710 | { | ||
711 | int rc = delete_fileobject(selected_file.path); | ||
712 | if (rc < FORC_SUCCESS) { | ||
713 | splash_failed(LANG_DELETE, rc); | ||
714 | } else if (rc == FORC_CANCELLED) { | ||
715 | splash_cancelled(); | ||
716 | } | ||
717 | if (rc != FORC_NOOP) { | ||
718 | /* Could have failed after some but not all needed changes; reload */ | ||
719 | onplay_result = ONPLAY_RELOAD_DIR; | ||
720 | } | ||
721 | return 1; | ||
722 | } | ||
723 | |||
724 | static void show_result(int rc, int lang_what) | ||
725 | { | ||
726 | if (rc < FORC_SUCCESS) { | ||
727 | splash_failed(lang_what, rc); | ||
728 | } else if (rc == FORC_CANCELLED) { | ||
729 | /* splash_cancelled(); kbd_input() splashes it */ | ||
730 | } else if (rc == FORC_SUCCESS) { | ||
731 | onplay_result = ONPLAY_RELOAD_DIR; | ||
732 | } | ||
733 | } | ||
734 | |||
735 | static int clipboard_create_dir(void) | ||
736 | { | ||
737 | int rc = create_dir(); | ||
738 | |||
739 | show_result(rc, LANG_CREATE_DIR); | ||
740 | |||
741 | return 1; | ||
742 | } | ||
743 | |||
744 | static int clipboard_rename_selected_file(void) | ||
745 | { | ||
746 | int rc = rename_file(selected_file.path); | ||
747 | |||
748 | show_result(rc, LANG_RENAME); | ||
749 | |||
750 | return 1; | ||
751 | } | ||
752 | |||
1252 | /* CONTEXT_[TREE|ID3DB] items */ | 753 | /* CONTEXT_[TREE|ID3DB] items */ |
1253 | static int clipboard_callback(int action, | 754 | static int clipboard_callback(int action, |
1254 | const struct menu_item_ex *this_item, | 755 | const struct menu_item_ex *this_item, |
1255 | struct gui_synclist *this_list); | 756 | struct gui_synclist *this_list); |
1256 | 757 | ||
1257 | MENUITEM_FUNCTION(rename_file_item, 0, ID2P(LANG_RENAME), | 758 | MENUITEM_FUNCTION(rename_file_item, 0, ID2P(LANG_RENAME), |
1258 | rename_file, clipboard_callback, Icon_NOICON); | 759 | clipboard_rename_selected_file, clipboard_callback, Icon_NOICON); |
1259 | MENUITEM_FUNCTION(clipboard_cut_item, 0, ID2P(LANG_CUT), | 760 | MENUITEM_FUNCTION(clipboard_cut_item, 0, ID2P(LANG_CUT), |
1260 | clipboard_cut, clipboard_callback, Icon_NOICON); | 761 | clipboard_cut, clipboard_callback, Icon_NOICON); |
1261 | MENUITEM_FUNCTION(clipboard_copy_item, 0, ID2P(LANG_COPY), | 762 | MENUITEM_FUNCTION(clipboard_copy_item, 0, ID2P(LANG_COPY), |
@@ -1263,16 +764,16 @@ MENUITEM_FUNCTION(clipboard_copy_item, 0, ID2P(LANG_COPY), | |||
1263 | MENUITEM_FUNCTION(clipboard_paste_item, 0, ID2P(LANG_PASTE), | 764 | MENUITEM_FUNCTION(clipboard_paste_item, 0, ID2P(LANG_PASTE), |
1264 | clipboard_paste, clipboard_callback, Icon_NOICON); | 765 | clipboard_paste, clipboard_callback, Icon_NOICON); |
1265 | MENUITEM_FUNCTION(delete_file_item, 0, ID2P(LANG_DELETE), | 766 | MENUITEM_FUNCTION(delete_file_item, 0, ID2P(LANG_DELETE), |
1266 | delete_file_dir, clipboard_callback, Icon_NOICON); | 767 | clipboard_delete_selected_fileobject, clipboard_callback, Icon_NOICON); |
1267 | MENUITEM_FUNCTION(delete_dir_item, 0, ID2P(LANG_DELETE_DIR), | 768 | MENUITEM_FUNCTION(delete_dir_item, 0, ID2P(LANG_DELETE_DIR), |
1268 | delete_file_dir, clipboard_callback, Icon_NOICON); | 769 | clipboard_delete_selected_fileobject, clipboard_callback, Icon_NOICON); |
1269 | MENUITEM_FUNCTION(create_dir_item, 0, ID2P(LANG_CREATE_DIR), | 770 | MENUITEM_FUNCTION(create_dir_item, 0, ID2P(LANG_CREATE_DIR), |
1270 | create_dir, clipboard_callback, Icon_NOICON); | 771 | clipboard_create_dir, clipboard_callback, Icon_NOICON); |
1271 | 772 | ||
1272 | /* other items */ | 773 | /* other items */ |
1273 | static bool list_viewers(void) | 774 | static bool list_viewers(void) |
1274 | { | 775 | { |
1275 | int ret = filetype_list_viewers(selected_file); | 776 | int ret = filetype_list_viewers(selected_file.path); |
1276 | if (ret == PLUGIN_USB_CONNECTED) | 777 | if (ret == PLUGIN_USB_CONNECTED) |
1277 | onplay_result = ONPLAY_RELOAD_DIR; | 778 | onplay_result = ONPLAY_RELOAD_DIR; |
1278 | return false; | 779 | return false; |
@@ -1281,19 +782,19 @@ static bool list_viewers(void) | |||
1281 | #ifdef HAVE_TAGCACHE | 782 | #ifdef HAVE_TAGCACHE |
1282 | static bool prepare_database_sel(void *param) | 783 | static bool prepare_database_sel(void *param) |
1283 | { | 784 | { |
1284 | if (context == CONTEXT_ID3DB && | 785 | if (selected_file.context == CONTEXT_ID3DB && |
1285 | (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) | 786 | (selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) |
1286 | { | 787 | { |
1287 | if (!strcmp(param, "properties")) | 788 | if (!strcmp(param, "properties")) |
1288 | strmemccpy(selected_file_path, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER), | 789 | strmemccpy(selected_file.buf, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER), |
1289 | sizeof(selected_file_path)); | 790 | sizeof(selected_file.buf)); |
1290 | else if (!tagtree_get_subentry_filename(selected_file_path, MAX_PATH)) | 791 | else if (!tagtree_get_subentry_filename(selected_file.buf, MAX_PATH)) |
1291 | { | 792 | { |
1292 | onplay_result = ONPLAY_RELOAD_DIR; | 793 | onplay_result = ONPLAY_RELOAD_DIR; |
1293 | return false; | 794 | return false; |
1294 | } | 795 | } |
1295 | 796 | ||
1296 | selected_file = selected_file_path; | 797 | selected_file.path = selected_file.buf; |
1297 | } | 798 | } |
1298 | return true; | 799 | return true; |
1299 | } | 800 | } |
@@ -1305,7 +806,7 @@ static bool onplay_load_plugin(void *param) | |||
1305 | if (!prepare_database_sel(param)) | 806 | if (!prepare_database_sel(param)) |
1306 | return false; | 807 | return false; |
1307 | #endif | 808 | #endif |
1308 | int ret = filetype_load_plugin((const char*)param, selected_file); | 809 | int ret = filetype_load_plugin((const char*)param, selected_file.path); |
1309 | if (ret == PLUGIN_USB_CONNECTED) | 810 | if (ret == PLUGIN_USB_CONNECTED) |
1310 | onplay_result = ONPLAY_RELOAD_DIR; | 811 | onplay_result = ONPLAY_RELOAD_DIR; |
1311 | else if (ret == PLUGIN_GOTO_PLUGIN) | 812 | else if (ret == PLUGIN_GOTO_PLUGIN) |
@@ -1330,19 +831,25 @@ MENUITEM_FUNCTION_W_PARAM(pictureflow_item, 0, ID2P(LANG_ONPLAY_PICTUREFLOW), | |||
1330 | #endif | 831 | #endif |
1331 | static bool onplay_add_to_shortcuts(void) | 832 | static bool onplay_add_to_shortcuts(void) |
1332 | { | 833 | { |
1333 | shortcuts_add(SHORTCUT_BROWSER, selected_file); | 834 | shortcuts_add(SHORTCUT_BROWSER, selected_file.path); |
1334 | return false; | 835 | return false; |
1335 | } | 836 | } |
1336 | MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES), | 837 | MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES), |
1337 | onplay_add_to_shortcuts, | 838 | onplay_add_to_shortcuts, |
1338 | clipboard_callback, Icon_NOICON); | 839 | clipboard_callback, Icon_NOICON); |
1339 | 840 | ||
841 | static void set_dir_helper(char* dirnamebuf, size_t bufsz) | ||
842 | { | ||
843 | path_append(dirnamebuf, selected_file.path, PA_SEP_HARD, bufsz); | ||
844 | settings_save(); | ||
845 | } | ||
846 | |||
1340 | #if LCD_DEPTH > 1 | 847 | #if LCD_DEPTH > 1 |
1341 | static bool set_backdrop(void) | 848 | static bool set_backdrop(void) |
1342 | { | 849 | { |
1343 | path_append(global_settings.backdrop_file, selected_file, | 850 | set_dir_helper(global_settings.backdrop_file, |
1344 | PA_SEP_HARD, sizeof(global_settings.backdrop_file)); | 851 | sizeof(global_settings.backdrop_file)); |
1345 | settings_save(); | 852 | |
1346 | skin_backdrop_load_setting(); | 853 | skin_backdrop_load_setting(); |
1347 | skin_backdrop_show(sb_get_backdrop(SCREEN_MAIN)); | 854 | skin_backdrop_show(sb_get_backdrop(SCREEN_MAIN)); |
1348 | return true; | 855 | return true; |
@@ -1353,9 +860,8 @@ MENUITEM_FUNCTION(set_backdrop_item, 0, ID2P(LANG_SET_AS_BACKDROP), | |||
1353 | #ifdef HAVE_RECORDING | 860 | #ifdef HAVE_RECORDING |
1354 | static bool set_recdir(void) | 861 | static bool set_recdir(void) |
1355 | { | 862 | { |
1356 | path_append(global_settings.rec_directory, selected_file, | 863 | set_dir_helper(global_settings.rec_directory, |
1357 | PA_SEP_HARD, sizeof(global_settings.rec_directory)); | 864 | sizeof(global_settings.rec_directory)); |
1358 | settings_save(); | ||
1359 | return false; | 865 | return false; |
1360 | } | 866 | } |
1361 | MENUITEM_FUNCTION(set_recdir_item, 0, ID2P(LANG_RECORDING_DIR), | 867 | MENUITEM_FUNCTION(set_recdir_item, 0, ID2P(LANG_RECORDING_DIR), |
@@ -1363,10 +869,8 @@ MENUITEM_FUNCTION(set_recdir_item, 0, ID2P(LANG_RECORDING_DIR), | |||
1363 | #endif | 869 | #endif |
1364 | static bool set_startdir(void) | 870 | static bool set_startdir(void) |
1365 | { | 871 | { |
1366 | path_append(global_settings.start_directory, selected_file, | 872 | set_dir_helper(global_settings.start_directory, |
1367 | PA_SEP_HARD, sizeof(global_settings.start_directory)); | 873 | sizeof(global_settings.start_directory)); |
1368 | |||
1369 | settings_save(); | ||
1370 | return false; | 874 | return false; |
1371 | } | 875 | } |
1372 | MENUITEM_FUNCTION(set_startdir_item, 0, ID2P(LANG_START_DIR), | 876 | MENUITEM_FUNCTION(set_startdir_item, 0, ID2P(LANG_START_DIR), |
@@ -1374,7 +878,7 @@ MENUITEM_FUNCTION(set_startdir_item, 0, ID2P(LANG_START_DIR), | |||
1374 | 878 | ||
1375 | static bool set_catalogdir(void) | 879 | static bool set_catalogdir(void) |
1376 | { | 880 | { |
1377 | catalog_set_directory(selected_file); | 881 | catalog_set_directory(selected_file.path); |
1378 | settings_save(); | 882 | settings_save(); |
1379 | return false; | 883 | return false; |
1380 | } | 884 | } |
@@ -1384,16 +888,14 @@ MENUITEM_FUNCTION(set_catalogdir_item, 0, ID2P(LANG_PLAYLIST_DIR), | |||
1384 | #ifdef HAVE_TAGCACHE | 888 | #ifdef HAVE_TAGCACHE |
1385 | static bool set_databasedir(void) | 889 | static bool set_databasedir(void) |
1386 | { | 890 | { |
1387 | path_append(global_settings.tagcache_db_path, selected_file, | ||
1388 | PA_SEP_SOFT, sizeof(global_settings.tagcache_db_path)); | ||
1389 | |||
1390 | struct tagcache_stat *tc_stat = tagcache_get_stat(); | 891 | struct tagcache_stat *tc_stat = tagcache_get_stat(); |
1391 | if (strcasecmp(global_settings.tagcache_db_path, tc_stat->db_path)) | 892 | if (strcasecmp(selected_file.path, tc_stat->db_path)) |
1392 | { | 893 | { |
1393 | splash(HZ, ID2P(LANG_PLEASE_REBOOT)); | 894 | splash(HZ, ID2P(LANG_PLEASE_REBOOT)); |
1394 | } | 895 | } |
1395 | 896 | ||
1396 | settings_save(); | 897 | set_dir_helper(global_settings.tagcache_db_path, |
898 | sizeof(global_settings.tagcache_db_path)); | ||
1397 | return false; | 899 | return false; |
1398 | } | 900 | } |
1399 | MENUITEM_FUNCTION(set_databasedir_item, 0, ID2P(LANG_DATABASE_DIR), | 901 | MENUITEM_FUNCTION(set_databasedir_item, 0, ID2P(LANG_DATABASE_DIR), |
@@ -1421,7 +923,7 @@ static int clipboard_callback(int action, | |||
1421 | case ACTION_REQUEST_MENUITEM: | 923 | case ACTION_REQUEST_MENUITEM: |
1422 | #ifdef HAVE_MULTIVOLUME | 924 | #ifdef HAVE_MULTIVOLUME |
1423 | /* no rename+delete for volumes */ | 925 | /* no rename+delete for volumes */ |
1424 | if ((selected_file_attr & ATTR_VOLUME) && | 926 | if ((selected_file.attr & ATTR_VOLUME) && |
1425 | (this_item == &rename_file_item || | 927 | (this_item == &rename_file_item || |
1426 | this_item == &delete_dir_item || | 928 | this_item == &delete_dir_item || |
1427 | this_item == &clipboard_cut_item || | 929 | this_item == &clipboard_cut_item || |
@@ -1429,7 +931,7 @@ static int clipboard_callback(int action, | |||
1429 | return ACTION_EXIT_MENUITEM; | 931 | return ACTION_EXIT_MENUITEM; |
1430 | #endif | 932 | #endif |
1431 | #ifdef HAVE_TAGCACHE | 933 | #ifdef HAVE_TAGCACHE |
1432 | if (context == CONTEXT_ID3DB) | 934 | if (selected_file.context == CONTEXT_ID3DB) |
1433 | { | 935 | { |
1434 | if (this_item == &track_info_item || | 936 | if (this_item == &track_info_item || |
1435 | this_item == &pictureflow_item) | 937 | this_item == &pictureflow_item) |
@@ -1447,21 +949,21 @@ static int clipboard_callback(int action, | |||
1447 | { | 949 | { |
1448 | return action; | 950 | return action; |
1449 | } | 951 | } |
1450 | else if (selected_file) | 952 | else if (selected_file.path) |
1451 | { | 953 | { |
1452 | /* requires an actual file */ | 954 | /* requires an actual file */ |
1453 | if (this_item == &rename_file_item || | 955 | if (this_item == &rename_file_item || |
1454 | this_item == &clipboard_cut_item || | 956 | this_item == &clipboard_cut_item || |
1455 | this_item == &clipboard_copy_item || | 957 | this_item == &clipboard_copy_item || |
1456 | (this_item == &track_info_item && | 958 | (this_item == &track_info_item && |
1457 | (selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) || | 959 | (selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) || |
1458 | (this_item == &properties_item && | 960 | (this_item == &properties_item && |
1459 | (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) || | 961 | (selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) || |
1460 | this_item == &add_to_faves_item) | 962 | this_item == &add_to_faves_item) |
1461 | { | 963 | { |
1462 | return action; | 964 | return action; |
1463 | } | 965 | } |
1464 | else if ((selected_file_attr & ATTR_DIRECTORY)) | 966 | else if ((selected_file.attr & ATTR_DIRECTORY)) |
1465 | { | 967 | { |
1466 | /* only for directories */ | 968 | /* only for directories */ |
1467 | if (this_item == &delete_dir_item || | 969 | if (this_item == &delete_dir_item || |
@@ -1486,7 +988,7 @@ static int clipboard_callback(int action, | |||
1486 | #if LCD_DEPTH > 1 | 988 | #if LCD_DEPTH > 1 |
1487 | else if (this_item == &set_backdrop_item) | 989 | else if (this_item == &set_backdrop_item) |
1488 | { | 990 | { |
1489 | char *suffix = strrchr(selected_file, '.'); | 991 | char *suffix = strrchr(selected_file.path, '.'); |
1490 | if (suffix) | 992 | if (suffix) |
1491 | { | 993 | { |
1492 | if (strcasecmp(suffix, ".bmp") == 0) | 994 | if (strcasecmp(suffix, ".bmp") == 0) |
@@ -1560,8 +1062,8 @@ static int onplaymenu_callback(int action, | |||
1560 | case ACTION_REQUEST_MENUITEM: | 1062 | case ACTION_REQUEST_MENUITEM: |
1561 | if (this_item == &view_playlist_item) | 1063 | if (this_item == &view_playlist_item) |
1562 | { | 1064 | { |
1563 | if ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U && | 1065 | if ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_M3U && |
1564 | context == CONTEXT_TREE) | 1066 | selected_file.context == CONTEXT_TREE) |
1565 | return action; | 1067 | return action; |
1566 | } | 1068 | } |
1567 | return ACTION_EXIT_MENUITEM; | 1069 | return ACTION_EXIT_MENUITEM; |
@@ -1569,6 +1071,8 @@ static int onplaymenu_callback(int action, | |||
1569 | case ACTION_EXIT_MENUITEM: | 1071 | case ACTION_EXIT_MENUITEM: |
1570 | return ACTION_EXIT_AFTER_THIS_MENUITEM; | 1072 | return ACTION_EXIT_AFTER_THIS_MENUITEM; |
1571 | break; | 1073 | break; |
1074 | default: | ||
1075 | break; | ||
1572 | } | 1076 | } |
1573 | return action; | 1077 | return action; |
1574 | } | 1078 | } |
@@ -1579,26 +1083,26 @@ static bool hotkey_delete_item(void) | |||
1579 | { | 1083 | { |
1580 | #ifdef HAVE_MULTIVOLUME | 1084 | #ifdef HAVE_MULTIVOLUME |
1581 | /* no delete for volumes */ | 1085 | /* no delete for volumes */ |
1582 | if (selected_file_attr & ATTR_VOLUME) | 1086 | if (selected_file.attr & ATTR_VOLUME) |
1583 | return false; | 1087 | return false; |
1584 | #endif | 1088 | #endif |
1585 | 1089 | ||
1586 | #ifdef HAVE_TAGCACHE | 1090 | #ifdef HAVE_TAGCACHE |
1587 | if (context == CONTEXT_ID3DB && | 1091 | if (selected_file.context == CONTEXT_ID3DB && |
1588 | (selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) | 1092 | (selected_file.attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) |
1589 | return false; | 1093 | return false; |
1590 | #endif | 1094 | #endif |
1591 | 1095 | ||
1592 | return delete_file_dir(); | 1096 | return clipboard_delete_selected_fileobject(); |
1593 | } | 1097 | } |
1594 | 1098 | ||
1595 | static bool hotkey_open_with(void) | 1099 | static bool hotkey_open_with(void) |
1596 | { | 1100 | { |
1597 | /* only open files */ | 1101 | /* only open files */ |
1598 | if (selected_file_attr & ATTR_DIRECTORY) | 1102 | if (selected_file.attr & ATTR_DIRECTORY) |
1599 | return false; | 1103 | return false; |
1600 | #ifdef HAVE_MULTIVOLUME | 1104 | #ifdef HAVE_MULTIVOLUME |
1601 | if (selected_file_attr & ATTR_VOLUME) | 1105 | if (selected_file.attr & ATTR_VOLUME) |
1602 | return false; | 1106 | return false; |
1603 | #endif | 1107 | #endif |
1604 | return list_viewers(); | 1108 | return list_viewers(); |
@@ -1607,8 +1111,8 @@ static bool hotkey_open_with(void) | |||
1607 | static int hotkey_tree_pl_insert_shuffled(void) | 1111 | static int hotkey_tree_pl_insert_shuffled(void) |
1608 | { | 1112 | { |
1609 | if ((audio_status() & AUDIO_STATUS_PLAY) || | 1113 | if ((audio_status() & AUDIO_STATUS_PLAY) || |
1610 | (selected_file_attr & ATTR_DIRECTORY) || | 1114 | (selected_file.attr & ATTR_DIRECTORY) || |
1611 | ((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U)) | 1115 | ((selected_file.attr & FILE_ATTR_MASK) == FILE_ATTR_M3U)) |
1612 | { | 1116 | { |
1613 | add_to_playlist(&addtopl_insert_shuf); | 1117 | add_to_playlist(&addtopl_insert_shuf); |
1614 | } | 1118 | } |
@@ -1621,7 +1125,7 @@ static int hotkey_tree_run_plugin(void *param) | |||
1621 | if (!prepare_database_sel(param)) | 1125 | if (!prepare_database_sel(param)) |
1622 | return ONPLAY_RELOAD_DIR; | 1126 | return ONPLAY_RELOAD_DIR; |
1623 | #endif | 1127 | #endif |
1624 | 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) |
1625 | return ONPLAY_START_PLAY; | 1129 | return ONPLAY_START_PLAY; |
1626 | 1130 | ||
1627 | return ONPLAY_RELOAD_DIR; | 1131 | return ONPLAY_RELOAD_DIR; |
@@ -1747,15 +1251,15 @@ static int execute_hotkey(bool is_wps) | |||
1747 | } | 1251 | } |
1748 | #endif /* HOTKEY */ | 1252 | #endif /* HOTKEY */ |
1749 | 1253 | ||
1750 | int onplay(char* file, int attr, int from, bool hotkey) | 1254 | int onplay(char* file, int attr, int from_context, bool hotkey) |
1751 | { | 1255 | { |
1752 | const struct menu_item_ex *menu; | 1256 | const struct menu_item_ex *menu; |
1753 | onplay_result = ONPLAY_OK; | 1257 | onplay_result = ONPLAY_OK; |
1754 | context = from; | ||
1755 | ctx_current_playlist_insert = NULL; | 1258 | ctx_current_playlist_insert = NULL; |
1756 | selected_file = NULL; | 1259 | selected_file_set(from_context, NULL, attr); |
1260 | |||
1757 | #ifdef HAVE_TAGCACHE | 1261 | #ifdef HAVE_TAGCACHE |
1758 | if (context == CONTEXT_ID3DB && | 1262 | if (from_context == CONTEXT_ID3DB && |
1759 | (attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) | 1263 | (attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) |
1760 | { | 1264 | { |
1761 | ctx_add_to_playlist = tagtree_add_to_playlist; | 1265 | ctx_add_to_playlist = tagtree_add_to_playlist; |
@@ -1763,8 +1267,8 @@ int onplay(char* file, int attr, int from, bool hotkey) | |||
1763 | { | 1267 | { |
1764 | /* add a leading slash so that catalog_add_to_a_playlist | 1268 | /* add a leading slash so that catalog_add_to_a_playlist |
1765 | later prefills the name when creating a new playlist */ | 1269 | later prefills the name when creating a new playlist */ |
1766 | snprintf(selected_file_path, MAX_PATH, "/%s", file); | 1270 | snprintf(selected_file.buf, MAX_PATH, "/%s", file); |
1767 | selected_file = selected_file_path; | 1271 | selected_file.path = selected_file.buf; |
1768 | } | 1272 | } |
1769 | } | 1273 | } |
1770 | else | 1274 | else |
@@ -1773,22 +1277,22 @@ int onplay(char* file, int attr, int from, bool hotkey) | |||
1773 | ctx_add_to_playlist = NULL; | 1277 | ctx_add_to_playlist = NULL; |
1774 | if (file != NULL) | 1278 | if (file != NULL) |
1775 | { | 1279 | { |
1776 | strmemccpy(selected_file_path, file, MAX_PATH); | 1280 | strmemccpy(selected_file.buf, file, MAX_PATH); |
1777 | selected_file = selected_file_path; | 1281 | selected_file.path = selected_file.buf; |
1778 | } | 1282 | } |
1779 | 1283 | ||
1780 | } | 1284 | } |
1781 | selected_file_attr = attr; | ||
1782 | int menu_selection; | 1285 | int menu_selection; |
1286 | |||
1783 | #ifdef HAVE_HOTKEY | 1287 | #ifdef HAVE_HOTKEY |
1784 | if (hotkey) | 1288 | if (hotkey) |
1785 | return execute_hotkey(context == CONTEXT_WPS); | 1289 | return execute_hotkey(from_context == CONTEXT_WPS); |
1786 | #else | 1290 | #else |
1787 | (void)hotkey; | 1291 | (void)hotkey; |
1788 | #endif | 1292 | #endif |
1789 | 1293 | ||
1790 | push_current_activity(ACTIVITY_CONTEXTMENU); | 1294 | push_current_activity(ACTIVITY_CONTEXTMENU); |
1791 | if (context == CONTEXT_WPS) | 1295 | if (from_context == CONTEXT_WPS) |
1792 | menu = &wps_onplay_menu; | 1296 | menu = &wps_onplay_menu; |
1793 | else | 1297 | else |
1794 | menu = &tree_onplay_menu; | 1298 | menu = &tree_onplay_menu; |
@@ -1797,23 +1301,22 @@ int onplay(char* file, int attr, int from, bool hotkey) | |||
1797 | if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* Activity may have been */ | 1301 | if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* Activity may have been */ |
1798 | pop_current_activity(); /* popped already by menu item */ | 1302 | pop_current_activity(); /* popped already by menu item */ |
1799 | 1303 | ||
1800 | switch (menu_selection) | 1304 | |
1801 | { | 1305 | if (menu_selection == GO_TO_WPS) |
1802 | case GO_TO_WPS: | 1306 | return ONPLAY_START_PLAY; |
1803 | return ONPLAY_START_PLAY; | 1307 | if (menu_selection == GO_TO_ROOT) |
1804 | case GO_TO_ROOT: | 1308 | return ONPLAY_MAINMENU; |
1805 | case GO_TO_MAINMENU: | 1309 | if (menu_selection == GO_TO_MAINMENU) |
1806 | return ONPLAY_MAINMENU; | 1310 | return ONPLAY_MAINMENU; |
1807 | case GO_TO_PLAYLIST_VIEWER: | 1311 | if (menu_selection == GO_TO_PLAYLIST_VIEWER) |
1808 | return ONPLAY_PLAYLIST; | 1312 | return ONPLAY_PLAYLIST; |
1809 | case GO_TO_PLUGIN: | 1313 | if (menu_selection == GO_TO_PLUGIN) |
1810 | return ONPLAY_PLUGIN; | 1314 | return ONPLAY_PLUGIN; |
1811 | default: | 1315 | |
1812 | return onplay_result; | 1316 | return onplay_result; |
1813 | } | ||
1814 | } | 1317 | } |
1815 | 1318 | ||
1816 | int get_onplay_context(void) | 1319 | int get_onplay_context(void) |
1817 | { | 1320 | { |
1818 | return context; | 1321 | return selected_file.context; |
1819 | } | 1322 | } |