summaryrefslogtreecommitdiff
path: root/apps/playlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playlist.c')
-rw-r--r--apps/playlist.c216
1 files changed, 198 insertions, 18 deletions
diff --git a/apps/playlist.c b/apps/playlist.c
index a2f46cf99f..ee09eecf40 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -86,6 +86,9 @@
86#include "button.h" 86#include "button.h"
87#include "filetree.h" 87#include "filetree.h"
88#include "abrepeat.h" 88#include "abrepeat.h"
89#include "dircache.h"
90#include "thread.h"
91#include "usb.h"
89#ifdef HAVE_LCD_BITMAP 92#ifdef HAVE_LCD_BITMAP
90#include "icons.h" 93#include "icons.h"
91#include "widgets.h" 94#include "widgets.h"
@@ -162,7 +165,7 @@ static int get_next_index(const struct playlist_info* playlist, int steps,
162static void find_and_set_playlist_index(struct playlist_info* playlist, 165static void find_and_set_playlist_index(struct playlist_info* playlist,
163 unsigned int seek); 166 unsigned int seek);
164static int compare(const void* p1, const void* p2); 167static int compare(const void* p1, const void* p2);
165static int get_filename(struct playlist_info* playlist, int seek, 168static int get_filename(struct playlist_info* playlist, int index, int seek,
166 bool control_file, char *buf, int buf_length); 169 bool control_file, char *buf, int buf_length);
167static int get_next_directory(char *dir); 170static int get_next_directory(char *dir);
168static int get_next_dir(char *dir, bool is_forward, bool recursion); 171static int get_next_dir(char *dir, bool is_forward, bool recursion);
@@ -175,6 +178,14 @@ static void display_buffer_full(void);
175static int flush_pending_control(struct playlist_info* playlist); 178static int flush_pending_control(struct playlist_info* playlist);
176static int rotate_index(const struct playlist_info* playlist, int index); 179static int rotate_index(const struct playlist_info* playlist, int index);
177 180
181#ifdef HAVE_DIRCACHE
182#define PLAYLIST_LOAD_POINTERS 1
183
184static struct event_queue playlist_queue;
185static long playlist_stack[(DEFAULT_STACK_SIZE + 0x400)/sizeof(long)];
186static const char playlist_thread_name[] = "playlist cachectrl";
187#endif
188
178/* 189/*
179 * remove any files and indices associated with the playlist 190 * remove any files and indices associated with the playlist
180 */ 191 */
@@ -394,11 +405,15 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
394 { 405 {
395 /* Store a new entry */ 406 /* Store a new entry */
396 playlist->indices[ playlist->amount ] = i+count; 407 playlist->indices[ playlist->amount ] = i+count;
397 playlist->amount++; 408#ifdef HAVE_DIRCACHE
409 if (playlist->filenames)
410 playlist->filenames[ playlist->amount ] = NULL;
411#endif
398 if ( playlist->amount >= playlist->max_playlist_size ) { 412 if ( playlist->amount >= playlist->max_playlist_size ) {
399 display_buffer_full(); 413 display_buffer_full();
400 return -1; 414 return -1;
401 } 415 }
416 playlist->amount++;
402 } 417 }
403 } 418 }
404 } 419 }
@@ -406,6 +421,10 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
406 i+= count; 421 i+= count;
407 } 422 }
408 423
424#ifdef HAVE_DIRCACHE
425 queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
426#endif
427
409 return 0; 428 return 0;
410} 429}
411 430
@@ -499,8 +518,14 @@ static int add_track_to_playlist(struct playlist_info* playlist,
499 518
500 /* shift indices so that track can be added */ 519 /* shift indices so that track can be added */
501 for (i=playlist->amount; i>insert_position; i--) 520 for (i=playlist->amount; i>insert_position; i--)
521 {
502 playlist->indices[i] = playlist->indices[i-1]; 522 playlist->indices[i] = playlist->indices[i-1];
503 523#ifdef HAVE_DIRCACHE
524 if (playlist->filenames)
525 playlist->filenames[i] = playlist->filenames[i-1];
526#endif
527 }
528
504 /* update stored indices if needed */ 529 /* update stored indices if needed */
505 if (playlist->amount > 0 && insert_position <= playlist->index) 530 if (playlist->amount > 0 && insert_position <= playlist->index)
506 playlist->index++; 531 playlist->index++;
@@ -554,6 +579,12 @@ static int add_track_to_playlist(struct playlist_info* playlist,
554 579
555 playlist->indices[insert_position] = flags | seek_pos; 580 playlist->indices[insert_position] = flags | seek_pos;
556 581
582#ifdef HAVE_DIRCACHE
583 if (playlist->filenames)
584 playlist->filenames[insert_position] = NULL;
585 queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
586#endif
587
557 playlist->amount++; 588 playlist->amount++;
558 playlist->num_inserted_tracks++; 589 playlist->num_inserted_tracks++;
559 590
@@ -693,7 +724,13 @@ static int remove_track_from_playlist(struct playlist_info* playlist,
693 724
694 /* shift indices now that track has been removed */ 725 /* shift indices now that track has been removed */
695 for (i=position; i<playlist->amount; i++) 726 for (i=position; i<playlist->amount; i++)
727 {
696 playlist->indices[i] = playlist->indices[i+1]; 728 playlist->indices[i] = playlist->indices[i+1];
729#ifdef HAVE_DIRCACHE
730 if (playlist->filenames)
731 playlist->filenames[i] = playlist->filenames[i+1];
732#endif
733 }
697 734
698 playlist->amount--; 735 playlist->amount--;
699 736
@@ -780,6 +817,14 @@ static int randomise_playlist(struct playlist_info* playlist,
780 store = playlist->indices[candidate]; 817 store = playlist->indices[candidate];
781 playlist->indices[candidate] = playlist->indices[count]; 818 playlist->indices[candidate] = playlist->indices[count];
782 playlist->indices[count] = store; 819 playlist->indices[count] = store;
820#ifdef HAVE_DIRCACHE
821 if (playlist->filenames)
822 {
823 store = (int)playlist->filenames[candidate];
824 playlist->filenames[candidate] = playlist->filenames[count];
825 playlist->filenames[count] = (struct dircache_entry *)store;
826 }
827#endif
783 } 828 }
784 829
785 if (start_current) 830 if (start_current)
@@ -817,6 +862,13 @@ static int sort_playlist(struct playlist_info* playlist, bool start_current,
817 qsort(playlist->indices, playlist->amount, 862 qsort(playlist->indices, playlist->amount,
818 sizeof(playlist->indices[0]), compare); 863 sizeof(playlist->indices[0]), compare);
819 864
865#ifdef HAVE_DIRCACHE
866 /** We need to re-check the song names from disk because qsort can't
867 * sort two arrays at once :/
868 * FIXME: Please implement a better way to do this. */
869 queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0);
870#endif
871
820 if (start_current) 872 if (start_current)
821 find_and_set_playlist_index(playlist, current); 873 find_and_set_playlist_index(playlist, current);
822 874
@@ -1040,10 +1092,88 @@ static int compare(const void* p1, const void* p2)
1040 return *e1 - *e2; 1092 return *e1 - *e2;
1041} 1093}
1042 1094
1095#ifdef HAVE_DIRCACHE
1096/**
1097 * Thread to update filename pointers to dircache on background
1098 * without affecting playlist load up performance.
1099 */
1100static void playlist_thread(void)
1101{
1102 struct event ev;
1103 bool dirty_pointers = false;
1104 static char tmp[MAX_PATH+1];
1105
1106 struct playlist_info *playlist;
1107 int index;
1108 int seek;
1109 bool control_file;
1110
1111 while (1)
1112 {
1113 queue_wait_w_tmo(&playlist_queue, &ev, HZ*5);
1114
1115 switch (ev.id)
1116 {
1117 case PLAYLIST_LOAD_POINTERS:
1118 dirty_pointers = true;
1119 break ;
1120
1121 /* Start the background scanning after 5s. */
1122 case SYS_TIMEOUT:
1123 if (!dirty_pointers)
1124 break ;
1125
1126 playlist = &current_playlist;
1127 if (!dircache_is_enabled() || !playlist->filenames
1128 || playlist->amount <= 0)
1129 break ;
1130
1131#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1132 cpu_boost(true);
1133#endif
1134 for (index = 0; index < playlist->amount
1135 && queue_empty(&playlist_queue); index++)
1136 {
1137 /* Process only pointers that are not already loaded. */
1138 if (playlist->filenames[index])
1139 continue ;
1140
1141 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
1142 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
1143
1144 /* Load the filename from playlist file. */
1145 if (get_filename(playlist, index, seek, control_file, tmp,
1146 sizeof(tmp)) < 0)
1147 break ;
1148
1149 /* Set the dircache entry pointer. */
1150 playlist->filenames[index] = dircache_get_entry_ptr(tmp);
1151
1152 /* And be on background so user doesn't notice any delays. */
1153 yield();
1154 }
1155
1156#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1157 cpu_boost(false);
1158#endif
1159 dirty_pointers = false;
1160 break ;
1161
1162#ifndef SIMULATOR
1163 case SYS_USB_CONNECTED:
1164 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1165 usb_wait_for_disconnect(&playlist_queue);
1166 break ;
1167#endif
1168 }
1169 }
1170}
1171#endif
1172
1043/* 1173/*
1044 * gets pathname for track at seek index 1174 * gets pathname for track at seek index
1045 */ 1175 */
1046static int get_filename(struct playlist_info* playlist, int seek, 1176static int get_filename(struct playlist_info* playlist, int index, int seek,
1047 bool control_file, char *buf, int buf_length) 1177 bool control_file, char *buf, int buf_length)
1048{ 1178{
1049 int fd; 1179 int fd;
@@ -1054,13 +1184,26 @@ static int get_filename(struct playlist_info* playlist, int seek,
1054 if (buf_length > MAX_PATH+1) 1184 if (buf_length > MAX_PATH+1)
1055 buf_length = MAX_PATH+1; 1185 buf_length = MAX_PATH+1;
1056 1186
1057 if (playlist->in_ram && !control_file) 1187#ifdef HAVE_DIRCACHE
1188 if (dircache_is_enabled() && playlist->filenames)
1189 {
1190 if (playlist->filenames[index] != NULL)
1191 {
1192 dircache_copy_path(playlist->filenames[index], tmp_buf, sizeof(tmp_buf)-1);
1193 max = strlen(tmp_buf) + 1;
1194 }
1195 }
1196#else
1197 (void)index;
1198#endif
1199
1200 if (playlist->in_ram && !control_file && max < 0)
1058 { 1201 {
1059 strncpy(tmp_buf, &playlist->buffer[seek], sizeof(tmp_buf)); 1202 strncpy(tmp_buf, &playlist->buffer[seek], sizeof(tmp_buf));
1060 tmp_buf[MAX_PATH] = '\0'; 1203 tmp_buf[MAX_PATH] = '\0';
1061 max = strlen(tmp_buf) + 1; 1204 max = strlen(tmp_buf) + 1;
1062 } 1205 }
1063 else 1206 else if (max < 0)
1064 { 1207 {
1065 if (control_file) 1208 if (control_file)
1066 fd = playlist->control_fd; 1209 fd = playlist->control_fd;
@@ -1482,6 +1625,16 @@ void playlist_init(void)
1482 playlist->buffer = buffer_alloc(playlist->buffer_size); 1625 playlist->buffer = buffer_alloc(playlist->buffer_size);
1483 mutex_init(&playlist->control_mutex); 1626 mutex_init(&playlist->control_mutex);
1484 empty_playlist(playlist, true); 1627 empty_playlist(playlist, true);
1628
1629#ifdef HAVE_DIRCACHE
1630 playlist->filenames = buffer_alloc(
1631 playlist->max_playlist_size * sizeof(int));
1632 memset(playlist->filenames, 0,
1633 playlist->max_playlist_size * sizeof(int));
1634 create_thread(playlist_thread, playlist_stack, sizeof(playlist_stack),
1635 playlist_thread_name);
1636 queue_init(&playlist_queue);
1637#endif
1485} 1638}
1486 1639
1487/* 1640/*
@@ -1906,8 +2059,9 @@ int playlist_add(const char *filename)
1906 return -1; 2059 return -1;
1907 } 2060 }
1908 2061
1909 playlist->indices[playlist->amount++] = playlist->buffer_end_pos; 2062 playlist->indices[playlist->amount] = playlist->buffer_end_pos;
1910 2063 playlist->amount++;
2064
1911 strcpy(&playlist->buffer[playlist->buffer_end_pos], filename); 2065 strcpy(&playlist->buffer[playlist->buffer_end_pos], filename);
1912 playlist->buffer_end_pos += len; 2066 playlist->buffer_end_pos += len;
1913 playlist->buffer[playlist->buffer_end_pos++] = '\0'; 2067 playlist->buffer[playlist->buffer_end_pos++] = '\0';
@@ -1991,7 +2145,7 @@ char* playlist_peek(int steps)
1991 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; 2145 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
1992 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; 2146 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
1993 2147
1994 if (get_filename(playlist, seek, control_file, now_playing, 2148 if (get_filename(playlist, index, seek, control_file, now_playing,
1995 MAX_PATH+1) < 0) 2149 MAX_PATH+1) < 0)
1996 return NULL; 2150 return NULL;
1997 2151
@@ -2003,11 +2157,21 @@ char* playlist_peek(int steps)
2003 (workaround for buggy playlist creation tools) */ 2157 (workaround for buggy playlist creation tools) */
2004 while (temp_ptr) 2158 while (temp_ptr)
2005 { 2159 {
2006 fd = open(temp_ptr, O_RDONLY); 2160#ifdef HAVE_DIRCACHE
2007 if (fd >= 0) 2161 if (dircache_is_enabled())
2008 { 2162 {
2009 close(fd); 2163 if (dircache_get_entry_ptr(temp_ptr))
2010 break; 2164 break;
2165 }
2166 else
2167#endif
2168 {
2169 fd = open(temp_ptr, O_RDONLY);
2170 if (fd >= 0)
2171 {
2172 close(fd);
2173 break;
2174 }
2011 } 2175 }
2012 2176
2013 temp_ptr = strchr(temp_ptr+1, '/'); 2177 temp_ptr = strchr(temp_ptr+1, '/');
@@ -2278,16 +2442,26 @@ int playlist_create_ex(struct playlist_info* playlist,
2278 { 2442 {
2279 int num_indices = index_buffer_size / sizeof(int); 2443 int num_indices = index_buffer_size / sizeof(int);
2280 2444
2445#ifdef HAVE_DIRCACHE
2446 num_indices /= 2;
2447#endif
2281 if (num_indices > global_settings.max_files_in_playlist) 2448 if (num_indices > global_settings.max_files_in_playlist)
2282 num_indices = global_settings.max_files_in_playlist; 2449 num_indices = global_settings.max_files_in_playlist;
2283 2450
2284 playlist->max_playlist_size = num_indices; 2451 playlist->max_playlist_size = num_indices;
2285 playlist->indices = index_buffer; 2452 playlist->indices = index_buffer;
2453#ifdef HAVE_DIRCACHE
2454 playlist->filenames = (const struct dircache_entry **)
2455 &playlist->indices[num_indices];
2456#endif
2286 } 2457 }
2287 else 2458 else
2288 { 2459 {
2289 playlist->max_playlist_size = current_playlist.max_playlist_size; 2460 playlist->max_playlist_size = current_playlist.max_playlist_size;
2290 playlist->indices = current_playlist.indices; 2461 playlist->indices = current_playlist.indices;
2462#ifdef HAVE_DIRCACHE
2463 playlist->filenames = current_playlist.filenames;
2464#endif
2291 } 2465 }
2292 2466
2293 playlist->buffer_size = 0; 2467 playlist->buffer_size = 0;
@@ -2336,9 +2510,15 @@ int playlist_set_current(struct playlist_info* playlist)
2336 current_playlist.dirlen = playlist->dirlen; 2510 current_playlist.dirlen = playlist->dirlen;
2337 2511
2338 if (playlist->indices && playlist->indices != current_playlist.indices) 2512 if (playlist->indices && playlist->indices != current_playlist.indices)
2513 {
2339 memcpy(current_playlist.indices, playlist->indices, 2514 memcpy(current_playlist.indices, playlist->indices,
2340 playlist->max_playlist_size*sizeof(int)); 2515 playlist->max_playlist_size*sizeof(int));
2341 2516#ifdef HAVE_DIRCACHE
2517 memcpy(current_playlist.filenames, playlist->filenames,
2518 playlist->max_playlist_size*sizeof(int));
2519#endif
2520 }
2521
2342 current_playlist.first_index = playlist->first_index; 2522 current_playlist.first_index = playlist->first_index;
2343 current_playlist.amount = playlist->amount; 2523 current_playlist.amount = playlist->amount;
2344 current_playlist.last_insert_pos = playlist->last_insert_pos; 2524 current_playlist.last_insert_pos = playlist->last_insert_pos;
@@ -2620,7 +2800,7 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index)
2620 queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK; 2800 queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK;
2621 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; 2801 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
2622 2802
2623 if (get_filename(playlist, seek, control_file, filename, 2803 if (get_filename(playlist, index, seek, control_file, filename,
2624 sizeof(filename)) < 0) 2804 sizeof(filename)) < 0)
2625 return -1; 2805 return -1;
2626 2806
@@ -2812,7 +2992,7 @@ int playlist_get_track_info(struct playlist_info* playlist, int index,
2812 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; 2992 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
2813 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; 2993 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
2814 2994
2815 if (get_filename(playlist, seek, control_file, info->filename, 2995 if (get_filename(playlist, index, seek, control_file, info->filename,
2816 sizeof(info->filename)) < 0) 2996 sizeof(info->filename)) < 0)
2817 return -1; 2997 return -1;
2818 2998
@@ -2883,7 +3063,7 @@ int playlist_save(struct playlist_info* playlist, char *filename)
2883 /* Don't save queued files */ 3063 /* Don't save queued files */
2884 if (!queue) 3064 if (!queue)
2885 { 3065 {
2886 if (get_filename(playlist, seek, control_file, tmp_buf, 3066 if (get_filename(playlist, index, seek, control_file, tmp_buf,
2887 MAX_PATH+1) < 0) 3067 MAX_PATH+1) < 0)
2888 { 3068 {
2889 result = -1; 3069 result = -1;