summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/filetree.c41
-rw-r--r--apps/playlist.c286
-rw-r--r--apps/playlist.h16
3 files changed, 166 insertions, 177 deletions
diff --git a/apps/filetree.c b/apps/filetree.c
index 7e6ba4eb8d..3e20c89924 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -72,29 +72,46 @@ static int strnatcasecmp_n(const char *a, const char *b, size_t n)
72int ft_build_playlist(struct tree_context* c, int start_index) 72int ft_build_playlist(struct tree_context* c, int start_index)
73{ 73{
74 int i; 74 int i;
75 int res = 0;
76 int start=start_index; 75 int start=start_index;
76 int res;
77 struct playlist_info *playlist = playlist_get_current(); 77 struct playlist_info *playlist = playlist_get_current();
78 78
79 tree_lock_cache(c); 79 tree_lock_cache(c);
80 struct entry *entries = tree_get_entries(c); 80 struct entry *entries = tree_get_entries(c);
81 81
82 for(i = 0;i < c->filesindir;i++) 82 struct playlist_insert_context pl_context;
83
84 res = playlist_insert_context_create(playlist, &pl_context,
85 PLAYLIST_REPLACE, false, false);
86 if (res >= 0)
83 { 87 {
84 if((entries[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) 88 cpu_boost(true);
89 for(i = 0;i < c->filesindir;i++)
85 { 90 {
86 res = playlist_insert_track(playlist, entries[i].name, 91#if 0 /*only needed if displaying progress */
87 PLAYLIST_INSERT_LAST, false, false); 92 /* user abort */
88 if (res < 0) 93 if (action_userabort(TIMEOUT_NOBLOCK))
94 {
89 break; 95 break;
96 }
97#endif
98 if((entries[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO)
99 {
100 res = playlist_insert_context_add(&pl_context, entries[i].name);
101 if (res < 0)
102 break;
103 }
104 else
105 {
106 /* Adjust the start index when se skip non-MP3 entries */
107 if(i < start)
108 start_index--;
109 }
90 } 110 }
91 else 111 cpu_boost(false);
92 {
93 /* Adjust the start index when se skip non-MP3 entries */
94 if(i < start)
95 start_index--;
96 }
97 } 112 }
113
114 playlist_insert_context_release(&pl_context);
98 115
99 tree_unlock_cache(c); 116 tree_unlock_cache(c);
100 return start_index; 117 return start_index;
diff --git a/apps/playlist.c b/apps/playlist.c
index 1314656c83..69634fb96d 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -166,13 +166,6 @@
166#define PLAYLIST_QUEUED 0x20000000 166#define PLAYLIST_QUEUED 0x20000000
167#define PLAYLIST_SKIPPED 0x10000000 167#define PLAYLIST_SKIPPED 0x10000000
168 168
169struct directory_search_context {
170 struct playlist_info* playlist;
171 int position;
172 bool queue;
173 int count;
174};
175
176static struct playlist_info current_playlist; 169static struct playlist_info current_playlist;
177 170
178static void dc_init_filerefs(struct playlist_info *playlist, 171static void dc_init_filerefs(struct playlist_info *playlist,
@@ -1435,41 +1428,7 @@ static int add_track_to_playlist_unlocked(struct playlist_info* playlist,
1435 */ 1428 */
1436static int directory_search_callback(char* filename, void* context) 1429static int directory_search_callback(char* filename, void* context)
1437{ 1430{
1438 struct directory_search_context* c = 1431 return playlist_insert_context_add(context, filename);
1439 (struct directory_search_context*) context;
1440 int insert_pos;
1441
1442 insert_pos = add_track_to_playlist_unlocked(c->playlist, filename,
1443 c->position, c->queue, -1);
1444
1445 if (insert_pos < 0)
1446 return -1;
1447
1448 (c->count)++;
1449
1450 /* After first INSERT_FIRST switch to INSERT so that all the
1451 rest of the tracks get inserted one after the other */
1452 if (c->position == PLAYLIST_INSERT_FIRST)
1453 c->position = PLAYLIST_INSERT;
1454
1455 if (((c->count)%PLAYLIST_DISPLAY_COUNT) == 0)
1456 {
1457 unsigned char* count_str;
1458
1459 if (c->queue)
1460 count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT);
1461 else
1462 count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT);
1463
1464 display_playlist_count(c->count, count_str, false);
1465
1466 if ((c->count) == PLAYLIST_DISPLAY_COUNT &&
1467 (audio_status() & AUDIO_STATUS_PLAY) &&
1468 c->playlist->started)
1469 audio_flush_and_reload_tracks();
1470 }
1471
1472 return 0;
1473} 1432}
1474 1433
1475/* 1434/*
@@ -2441,27 +2400,27 @@ int playlist_get_track_info(struct playlist_info* playlist, int index,
2441} 2400}
2442 2401
2443/* 2402/*
2444 * Insert all tracks from specified directory into playlist. 2403 * initialize an insert context to add tracks to a playlist
2404 * don't forget to release it when finished adding files
2445 */ 2405 */
2446int playlist_insert_directory(struct playlist_info* playlist, 2406int playlist_insert_context_create(struct playlist_info* playlist,
2447 const char *dirname, int position, bool queue, 2407 struct playlist_insert_context *context,
2448 bool recurse) 2408 int position, bool queue, bool progress)
2449{ 2409{
2450 int result;
2451 unsigned char *count_str;
2452 struct directory_search_context context;
2453 2410
2454 if (!playlist) 2411 if (!playlist)
2455 playlist = &current_playlist; 2412 playlist = &current_playlist;
2456 2413
2414 context->playlist = playlist;
2415 context->initialized = false;
2416
2457 dc_thread_stop(playlist); 2417 dc_thread_stop(playlist);
2458 playlist_write_lock(playlist); 2418 playlist_write_lock(playlist);
2459 2419
2460 if (check_control(playlist) < 0) 2420 if (check_control(playlist) < 0)
2461 { 2421 {
2462 notify_control_access_error(); 2422 notify_control_access_error();
2463 result = -1; 2423 return -1;
2464 goto out;
2465 } 2424 }
2466 2425
2467 if (position == PLAYLIST_REPLACE) 2426 if (position == PLAYLIST_REPLACE)
@@ -2470,41 +2429,101 @@ int playlist_insert_directory(struct playlist_info* playlist,
2470 position = PLAYLIST_INSERT_LAST; 2429 position = PLAYLIST_INSERT_LAST;
2471 else 2430 else
2472 { 2431 {
2473 result = -1; 2432 return -1;
2474 goto out;
2475 } 2433 }
2476 } 2434 }
2477 2435
2436 context->playlist = playlist;
2437 context->position = position;
2438 context->queue = queue;
2439 context->count = 0;
2440 context->progress = progress;
2441 context->initialized = true;
2442
2478 if (queue) 2443 if (queue)
2479 count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT); 2444 context->count_langid = LANG_PLAYLIST_QUEUE_COUNT;
2480 else 2445 else
2481 count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT); 2446 context->count_langid = LANG_PLAYLIST_INSERT_COUNT;
2482 2447
2483 display_playlist_count(0, count_str, false); 2448 return 0;
2449}
2484 2450
2485 context.playlist = playlist; 2451/*
2486 context.position = position; 2452 * add tracks to playlist using opened insert context
2487 context.queue = queue; 2453 */
2488 context.count = 0; 2454int playlist_insert_context_add(struct playlist_insert_context *context,
2455 const char *filename)
2456{
2457 struct playlist_insert_context* c = context;
2458 int insert_pos;
2489 2459
2490 cpu_boost(true); 2460 insert_pos = add_track_to_playlist_unlocked(c->playlist, filename,
2461 c->position, c->queue, -1);
2491 2462
2492 result = playlist_directory_tracksearch(dirname, recurse, 2463 if (insert_pos < 0)
2493 directory_search_callback, &context); 2464 return -1;
2494 2465
2495 sync_control_unlocked(playlist); 2466 (c->count)++;
2496 2467
2497 cpu_boost(false); 2468 /* After first INSERT_FIRST switch to INSERT so that all the
2469 rest of the tracks get inserted one after the other */
2470 if (c->position == PLAYLIST_INSERT_FIRST)
2471 c->position = PLAYLIST_INSERT;
2498 2472
2499 display_playlist_count(context.count, count_str, true); 2473 if (((c->count)%PLAYLIST_DISPLAY_COUNT) == 0)
2474 {
2475 if (c->progress)
2476 display_playlist_count(c->count, ID2P(c->count_langid), false);
2477
2478 if ((c->count) == PLAYLIST_DISPLAY_COUNT &&
2479 (audio_status() & AUDIO_STATUS_PLAY) &&
2480 c->playlist->started)
2481 audio_flush_and_reload_tracks();
2482 }
2483
2484 return 0;
2485}
2486
2487/*
2488 * release opened insert context, sync playlist
2489 */
2490void playlist_insert_context_release(struct playlist_insert_context *context)
2491{
2492
2493 struct playlist_info* playlist = context->playlist;
2494 if (context->initialized)
2495 sync_control_unlocked(playlist);
2496 if (context->progress)
2497 display_playlist_count(context->count, ID2P(context->count_langid), true);
2500 2498
2501out:
2502 playlist_write_unlock(playlist); 2499 playlist_write_unlock(playlist);
2503 dc_thread_start(playlist, true); 2500 dc_thread_start(playlist, true);
2504 2501
2505 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) 2502 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
2506 audio_flush_and_reload_tracks(); 2503 audio_flush_and_reload_tracks();
2504}
2505
2506/*
2507 * Insert all tracks from specified directory into playlist.
2508 */
2509int playlist_insert_directory(struct playlist_info* playlist,
2510 const char *dirname, int position, bool queue,
2511 bool recurse)
2512{
2513 int result = -1;
2514 struct playlist_insert_context context;
2515 result = playlist_insert_context_create(playlist, &context,
2516 position, queue, true);
2517 if (result >= 0)
2518 {
2519 cpu_boost(true);
2520
2521 result = playlist_directory_tracksearch(dirname, recurse,
2522 directory_search_callback, &context);
2507 2523
2524 cpu_boost(false);
2525 }
2526 playlist_insert_context_release(&context);
2508 return result; 2527 return result;
2509} 2528}
2510 2529
@@ -2514,133 +2533,70 @@ out:
2514int playlist_insert_playlist(struct playlist_info* playlist, const char *filename, 2533int playlist_insert_playlist(struct playlist_info* playlist, const char *filename,
2515 int position, bool queue) 2534 int position, bool queue)
2516{ 2535{
2517 int fd; 2536 int fd = -1;
2518 int max; 2537 int max;
2519 char *dir; 2538 char *dir;
2520 unsigned char *count_str; 2539
2521 char temp_buf[MAX_PATH+1]; 2540 char temp_buf[MAX_PATH+1];
2522 char trackname[MAX_PATH+1]; 2541 char trackname[MAX_PATH+1];
2523 int count = 0; 2542
2524 int result = -1; 2543 int result = -1;
2525 bool utf8 = is_m3u8_name(filename); 2544 bool utf8 = is_m3u8_name(filename);
2526 2545
2527 if (!playlist) 2546 struct playlist_insert_context pl_context;
2528 playlist = &current_playlist;
2529
2530 dc_thread_stop(playlist);
2531 playlist_write_lock(playlist);
2532
2533 cpu_boost(true); 2547 cpu_boost(true);
2534 2548
2535 if (check_control(playlist) < 0) 2549 if (playlist_insert_context_create(playlist, &pl_context, position, queue, true) >= 0)
2536 { 2550 {
2537 notify_control_access_error(); 2551 fd = open_utf8(filename, O_RDONLY);
2538 goto out; 2552 if (fd < 0)
2539 }
2540
2541 fd = open_utf8(filename, O_RDONLY);
2542 if (fd < 0)
2543 {
2544 notify_access_error();
2545 goto out;
2546 }
2547
2548 /* we need the directory name for formatting purposes */
2549 size_t dirlen = path_dirname(filename, (const char **)&dir);
2550 dir = strmemdupa(dir, dirlen);
2551
2552 if (queue)
2553 count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT);
2554 else
2555 count_str = ID2P(LANG_PLAYLIST_INSERT_COUNT);
2556
2557 display_playlist_count(count, count_str, false);
2558
2559 if (position == PLAYLIST_REPLACE)
2560 {
2561 if (remove_all_tracks_unlocked(playlist, true) == 0)
2562 position = PLAYLIST_INSERT_LAST;
2563 else
2564 { 2553 {
2565 close(fd); 2554 notify_access_error();
2566 goto out; 2555 goto out;
2567 } 2556 }
2568 }
2569 2557
2570 while ((max = read_line(fd, temp_buf, sizeof(temp_buf))) > 0) 2558 /* we need the directory name for formatting purposes */
2571 { 2559 size_t dirlen = path_dirname(filename, (const char **)&dir);
2572 /* user abort */ 2560 dir = strmemdupa(dir, dirlen);
2573 if (action_userabort(TIMEOUT_NOBLOCK))
2574 break;
2575 2561
2576 if (temp_buf[0] != '#' && temp_buf[0] != '\0') 2562 while ((max = read_line(fd, temp_buf, sizeof(temp_buf))) > 0)
2577 { 2563 {
2578 int insert_pos; 2564 /* user abort */
2579 2565 if (action_userabort(TIMEOUT_NOBLOCK))
2580 if (!utf8) 2566 break;
2581 {
2582 /* Use trackname as a temporay buffer. Note that trackname must
2583 * be as large as temp_buf.
2584 */
2585 max = convert_m3u_name(temp_buf, max, sizeof(temp_buf), trackname);
2586 }
2587
2588 /* we need to format so that relative paths are correctly
2589 handled */
2590 if (format_track_path(trackname, temp_buf, sizeof(trackname), dir) < 0)
2591 {
2592 goto out;
2593 }
2594
2595 insert_pos = add_track_to_playlist_unlocked(playlist, trackname,
2596 position, queue, -1);
2597
2598 if (insert_pos < 0)
2599 {
2600 goto out;
2601 }
2602
2603 /* After first INSERT_FIRST switch to INSERT so that all the
2604 rest of the tracks get inserted one after the other */
2605 if (position == PLAYLIST_INSERT_FIRST)
2606 position = PLAYLIST_INSERT;
2607
2608 count++;
2609 2567
2610 if ((count%PLAYLIST_DISPLAY_COUNT) == 0) 2568 if (temp_buf[0] != '#' && temp_buf[0] != '\0')
2611 { 2569 {
2612 display_playlist_count(count, count_str, false); 2570 if (!utf8)
2571 {
2572 /* Use trackname as a temporay buffer. Note that trackname must
2573 * be as large as temp_buf.
2574 */
2575 max = convert_m3u_name(temp_buf, max, sizeof(temp_buf), trackname);
2576 }
2613 2577
2614 if (count == PLAYLIST_DISPLAY_COUNT && 2578 /* we need to format so that relative paths are correctly
2615 (audio_status() & AUDIO_STATUS_PLAY) && 2579 handled */
2616 playlist->started) 2580 if (format_track_path(trackname, temp_buf, sizeof(trackname), dir) < 0)
2617 { 2581 {
2618 audio_flush_and_reload_tracks(); 2582 goto out;
2619 } 2583 }
2584
2585 if (playlist_insert_context_add(&pl_context, trackname) < 0)
2586 goto out;
2620 } 2587 }
2621 }
2622 2588
2623 /* let the other threads work */ 2589 /* let the other threads work */
2624 yield(); 2590 yield();
2591 }
2625 } 2592 }
2626 2593
2627 close(fd);
2628
2629 sync_control_unlocked(playlist);
2630
2631 display_playlist_count(count, count_str, true);
2632
2633 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
2634 audio_flush_and_reload_tracks();
2635
2636 result = 0; 2594 result = 0;
2637 2595
2638out: 2596out:
2597 close(fd);
2639 cpu_boost(false); 2598 cpu_boost(false);
2640 2599 playlist_insert_context_release(&pl_context);
2641 playlist_write_unlock(playlist);
2642 dc_thread_start(playlist, true);
2643
2644 return result; 2600 return result;
2645} 2601}
2646 2602
diff --git a/apps/playlist.h b/apps/playlist.h
index a12180f286..6d86270bc4 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -98,6 +98,16 @@ struct playlist_track_info
98 int display_index; /* index of track for display */ 98 int display_index; /* index of track for display */
99}; 99};
100 100
101struct playlist_insert_context {
102 struct playlist_info* playlist;
103 int position;
104 bool queue;
105 bool progress;
106 bool initialized;
107 int count;
108 int32_t count_langid;
109};
110
101/* Exported functions only for current playlist. */ 111/* Exported functions only for current playlist. */
102void playlist_init(void) INIT_ATTR; 112void playlist_init(void) INIT_ATTR;
103void playlist_shutdown(void); 113void playlist_shutdown(void);
@@ -132,6 +142,12 @@ void playlist_close(struct playlist_info* playlist);
132void playlist_sync(struct playlist_info* playlist); 142void playlist_sync(struct playlist_info* playlist);
133int playlist_insert_track(struct playlist_info* playlist, const char *filename, 143int playlist_insert_track(struct playlist_info* playlist, const char *filename,
134 int position, bool queue, bool sync); 144 int position, bool queue, bool sync);
145int playlist_insert_context_create(struct playlist_info* playlist,
146 struct playlist_insert_context *context,
147 int position, bool queue, bool progress);
148int playlist_insert_context_add(struct playlist_insert_context *context,
149 const char *filename);
150void playlist_insert_context_release(struct playlist_insert_context *context);
135int playlist_insert_directory(struct playlist_info* playlist, 151int playlist_insert_directory(struct playlist_info* playlist,
136 const char *dirname, int position, bool queue, 152 const char *dirname, int position, bool queue,
137 bool recurse); 153 bool recurse);