summaryrefslogtreecommitdiff
path: root/apps/playlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playlist.c')
-rw-r--r--apps/playlist.c467
1 files changed, 246 insertions, 221 deletions
diff --git a/apps/playlist.c b/apps/playlist.c
index 7b7b91c22f..bf65bb8656 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -67,6 +67,7 @@
67 flushed to disk when required. 67 flushed to disk when required.
68 */ 68 */
69 69
70//#define LOGF_ENABLE
70#include <stdio.h> 71#include <stdio.h>
71#include <stdlib.h> 72#include <stdlib.h>
72#include <ctype.h> 73#include <ctype.h>
@@ -106,11 +107,9 @@
106#ifdef HAVE_DIRCACHE 107#ifdef HAVE_DIRCACHE
107#include "dircache.h" 108#include "dircache.h"
108#endif 109#endif
110#include "logf.h"
109 111
110#if 0//def ROCKBOX_HAS_LOGDISKF 112#if 0//def ROCKBOX_HAS_LOGDISKF
111#warning LOGF enabled
112#define LOGF_ENABLE
113#include "logf.h"
114#undef DEBUGF 113#undef DEBUGF
115#undef ERRORF 114#undef ERRORF
116#undef WARNF 115#undef WARNF
@@ -119,9 +118,6 @@
119#define ERRORF DEBUGF 118#define ERRORF DEBUGF
120#define WARNF DEBUGF 119#define WARNF DEBUGF
121#define NOTEF DEBUGF 120#define NOTEF DEBUGF
122//ERRORF
123//WARNF
124//NOTEF
125#endif 121#endif
126 122
127/* default load buffer size (should be at least 1 KiB) */ 123/* default load buffer size (should be at least 1 KiB) */
@@ -190,12 +186,11 @@ static void dc_init_filerefs(struct playlist_info *playlist,
190} 186}
191 187
192#ifdef HAVE_DIRCACHE 188#ifdef HAVE_DIRCACHE
193#define PLAYLIST_LOAD_POINTERS 1 189#define PLAYLIST_DC_SCAN_START 1
194#define PLAYLIST_CLEAN_POINTERS 2 190#define PLAYLIST_DC_SCAN_STOP 2
195static bool dc_has_dirty_pointers = false;
196 191
197static struct event_queue playlist_queue SHAREDBSS_ATTR; 192static struct event_queue playlist_queue;
198static struct queue_sender_list playlist_queue_sender_list SHAREDBSS_ATTR; 193static struct queue_sender_list playlist_queue_sender_list;
199static long playlist_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; 194static long playlist_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)];
200static const char dc_thread_playlist_name[] = "playlist cachectrl"; 195static const char dc_thread_playlist_name[] = "playlist cachectrl";
201#endif 196#endif
@@ -232,22 +227,20 @@ static void notify_buffer_full(void)
232 splash(HZ*2, ID2P(LANG_PLAYLIST_BUFFER_FULL)); 227 splash(HZ*2, ID2P(LANG_PLAYLIST_BUFFER_FULL));
233} 228}
234 229
235static void dc_load_playlist_pointers(void) 230static void dc_thread_start(struct playlist_info *playlist, bool is_dirty)
236{ 231{
237#ifdef HAVE_DIRCACHE 232#ifdef HAVE_DIRCACHE
238 queue_post(&playlist_queue, PLAYLIST_LOAD_POINTERS, 0); 233 if (playlist == &current_playlist)
234 queue_post(&playlist_queue, PLAYLIST_DC_SCAN_START, is_dirty);
239#endif 235#endif
240/* No-Op for non dircache targets */
241} 236}
242 237
243static void dc_discard_playlist_pointers(void) 238static void dc_thread_stop(struct playlist_info *playlist)
244{ 239{
245#ifdef HAVE_DIRCACHE 240#ifdef HAVE_DIRCACHE
246 /* dump any pointers currently waiting */ 241 if (playlist == &current_playlist)
247 if (dc_has_dirty_pointers) 242 queue_send(&playlist_queue, PLAYLIST_DC_SCAN_STOP, 0);
248 queue_send(&playlist_queue, PLAYLIST_CLEAN_POINTERS, 0);
249#endif 243#endif
250/* No-Op for non dircache targets */
251} 244}
252 245
253static void close_playlist_control_file(struct playlist_info *playlist) 246static void close_playlist_control_file(struct playlist_info *playlist)
@@ -547,8 +540,6 @@ static void update_playlist_filename_unlocked(struct playlist_info* playlist,
547 */ 540 */
548static void empty_playlist_unlocked(struct playlist_info* playlist, bool resume) 541static void empty_playlist_unlocked(struct playlist_info* playlist, bool resume)
549{ 542{
550 dc_discard_playlist_pointers();
551
552 if(playlist->fd >= 0) /* If there is an already open playlist, close it. */ 543 if(playlist->fd >= 0) /* If there is an already open playlist, close it. */
553 { 544 {
554 close(playlist->fd); 545 close(playlist->fd);
@@ -1556,8 +1547,8 @@ static int directory_search_callback(char* filename, void* context)
1556/* 1547/*
1557 * remove track at specified position 1548 * remove track at specified position
1558 */ 1549 */
1559static int remove_track_from_playlist(struct playlist_info* playlist, 1550static int remove_track_unlocked(struct playlist_info* playlist,
1560 int position, bool write) 1551 int position, bool write)
1561{ 1552{
1562 int i; 1553 int i;
1563 int result = 0; 1554 int result = 0;
@@ -1566,8 +1557,6 @@ static int remove_track_from_playlist(struct playlist_info* playlist,
1566 if (playlist->amount <= 0) 1557 if (playlist->amount <= 0)
1567 return -1; 1558 return -1;
1568 1559
1569 playlist_mutex_lock(&(playlist->mutex));
1570
1571 inserted = playlist->indices[position] & PLAYLIST_INSERT_TYPE_MASK; 1560 inserted = playlist->indices[position] & PLAYLIST_INSERT_TYPE_MASK;
1572 1561
1573#ifdef HAVE_DIRCACHE 1562#ifdef HAVE_DIRCACHE
@@ -1613,7 +1602,6 @@ static int remove_track_from_playlist(struct playlist_info* playlist,
1613 sync_control(playlist, false); 1602 sync_control(playlist, false);
1614 } 1603 }
1615 1604
1616 playlist_mutex_unlock(&(playlist->mutex));
1617 return result; 1605 return result;
1618} 1606}
1619 1607
@@ -1642,18 +1630,14 @@ static void find_and_set_playlist_index_unlocked(struct playlist_info* playlist,
1642 * randomly rearrange the array of indices for the playlist. If start_current 1630 * randomly rearrange the array of indices for the playlist. If start_current
1643 * is true then update the index to the new index of the current playing track 1631 * is true then update the index to the new index of the current playing track
1644 */ 1632 */
1645static int randomise_playlist(struct playlist_info* playlist, 1633static int randomise_playlist_unlocked(struct playlist_info* playlist,
1646 unsigned int seed, bool start_current, 1634 unsigned int seed, bool start_current,
1647 bool write) 1635 bool write)
1648{ 1636{
1649 int count; 1637 int count;
1650 int candidate; 1638 int candidate;
1651 unsigned int current = playlist->indices[playlist->index]; 1639 unsigned int current = playlist->indices[playlist->index];
1652 1640
1653 playlist_mutex_lock(&(playlist->mutex));
1654
1655 dc_discard_playlist_pointers();
1656
1657 /* seed 0 is used to identify sorted playlist for resume purposes */ 1641 /* seed 0 is used to identify sorted playlist for resume purposes */
1658 if (seed == 0) 1642 if (seed == 0)
1659 seed = 1; 1643 seed = 1;
@@ -1698,8 +1682,6 @@ static int randomise_playlist(struct playlist_info* playlist,
1698 playlist->first_index, NULL, NULL, NULL); 1682 playlist->first_index, NULL, NULL, NULL);
1699 } 1683 }
1700 1684
1701 playlist_mutex_unlock(&(playlist->mutex));
1702
1703 return 0; 1685 return 0;
1704} 1686}
1705 1687
@@ -1740,8 +1722,6 @@ static int sort_playlist_unlocked(struct playlist_info* playlist,
1740{ 1722{
1741 unsigned int current = playlist->indices[playlist->index]; 1723 unsigned int current = playlist->indices[playlist->index];
1742 1724
1743 dc_discard_playlist_pointers();
1744
1745 if (playlist->amount > 0) 1725 if (playlist->amount > 0)
1746 qsort((void*)playlist->indices, playlist->amount, 1726 qsort((void*)playlist->indices, playlist->amount,
1747 sizeof(playlist->indices[0]), sort_compare_fn); 1727 sizeof(playlist->indices[0]), sort_compare_fn);
@@ -1751,7 +1731,6 @@ static int sort_playlist_unlocked(struct playlist_info* playlist,
1751 * sort two arrays at once :/ 1731 * sort two arrays at once :/
1752 * FIXME: Please implement a better way to do this. */ 1732 * FIXME: Please implement a better way to do this. */
1753 dc_init_filerefs(playlist, 0, playlist->max_playlist_size); 1733 dc_init_filerefs(playlist, 0, playlist->max_playlist_size);
1754 dc_load_playlist_pointers();
1755#endif 1734#endif
1756 1735
1757 if (start_current) 1736 if (start_current)
@@ -1917,55 +1896,81 @@ static void dc_thread_playlist(void)
1917 int seek; 1896 int seek;
1918 bool control_file; 1897 bool control_file;
1919 1898
1920 int sleep_time = 5; 1899 /* Thread starts out stopped */
1921 1900 long sleep_time = TIMEOUT_BLOCK;
1922#ifdef HAVE_DISK_STORAGE 1901 int stop_count = 1;
1923 if (global_settings.disk_spindown > 1 && 1902 bool is_dirty = false;
1924 global_settings.disk_spindown <= 5)
1925 sleep_time = global_settings.disk_spindown - 1;
1926#endif
1927 1903
1928 while (1) 1904 while (1)
1929 { 1905 {
1930 queue_wait_w_tmo(&playlist_queue, &ev, HZ*sleep_time); 1906 queue_wait_w_tmo(&playlist_queue, &ev, sleep_time);
1931 1907
1932 switch (ev.id) 1908 switch (ev.id)
1933 { 1909 {
1934 case PLAYLIST_CLEAN_POINTERS: 1910 case PLAYLIST_DC_SCAN_START:
1935 dc_has_dirty_pointers = false; 1911 if (ev.data)
1936 queue_reply(&playlist_queue, 0); 1912 is_dirty = true;
1913
1914 stop_count--;
1915 if (is_dirty && stop_count == 0)
1916 {
1917 /* Start the background scanning after either the disk
1918 * spindown timeout or 5s, whichever is less */
1919 sleep_time = 5 * HZ;
1920#ifdef HAVE_DISK_STORAGE
1921 if (global_settings.disk_spindown > 1 &&
1922 global_settings.disk_spindown <= 5)
1923 sleep_time = (global_settings.disk_spindown - 1) * HZ;
1924#endif
1925 }
1937 break; 1926 break;
1938 1927
1939 case PLAYLIST_LOAD_POINTERS: 1928 case PLAYLIST_DC_SCAN_STOP:
1940 dc_has_dirty_pointers = true; 1929 stop_count++;
1941 break ; 1930 sleep_time = TIMEOUT_BLOCK;
1931 queue_reply(&playlist_queue, 0);
1932 break;
1942 1933
1943 /* Start the background scanning after either the disk spindown
1944 timeout or 5s, whichever is less */
1945 case SYS_TIMEOUT: 1934 case SYS_TIMEOUT:
1946 { 1935 {
1936 /* Nothing to do if there are no dcfrefs or tracks */
1947 if (!playlist->dcfrefs_handle || playlist->amount <= 0) 1937 if (!playlist->dcfrefs_handle || playlist->amount <= 0)
1948 break ; 1938 {
1949 1939 is_dirty = false;
1950 /* Check if previously loaded pointers are intact. */ 1940 sleep_time = TIMEOUT_BLOCK;
1951 if (!dc_has_dirty_pointers) 1941 logf("%s: nothing to scan", __func__);
1952 break ; 1942 break;
1943 }
1953 1944
1945 /* Retry at a later time if the dircache is not ready */
1954 struct dircache_info info; 1946 struct dircache_info info;
1955 dircache_get_info(&info); 1947 dircache_get_info(&info);
1956
1957 if (info.status != DIRCACHE_READY) 1948 if (info.status != DIRCACHE_READY)
1958 break ; 1949 {
1950 logf("%s: dircache not ready", __func__);
1951 break;
1952 }
1953
1954 logf("%s: scan start", __func__);
1955#ifdef LOGF_ENABLE
1956 long scan_start_tick = current_tick;
1957#endif
1959 1958
1960 trigger_cpu_boost(); 1959 trigger_cpu_boost();
1961 dcfrefs = core_get_data_pinned(playlist->dcfrefs_handle); 1960 dcfrefs = core_get_data_pinned(playlist->dcfrefs_handle);
1962 1961
1963 for (index = 0; index < playlist->amount 1962 for (index = 0; index < playlist->amount; index++)
1964 && queue_empty(&playlist_queue); index++)
1965 { 1963 {
1966 /* Process only pointers that are superficially stale. */ 1964 /* Process only pointers that are superficially stale. */
1967 if (dircache_search(DCS_FILEREF, &dcfrefs[index], NULL) > 0) 1965 if (dircache_search(DCS_FILEREF, &dcfrefs[index], NULL) > 0)
1968 continue ; 1966 continue;
1967
1968 /* Bail out if a command needs servicing. */
1969 if (!queue_empty(&playlist_queue))
1970 {
1971 logf("%s: scan interrupted", __func__);
1972 break;
1973 }
1969 1974
1970 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; 1975 control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK;
1971 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK; 1976 seek = playlist->indices[index] & PLAYLIST_SEEK_MASK;
@@ -1973,9 +1978,7 @@ static void dc_thread_playlist(void)
1973 /* Load the filename from playlist file. */ 1978 /* Load the filename from playlist file. */
1974 if (get_track_filename(playlist, index, seek, 1979 if (get_track_filename(playlist, index, seek,
1975 control_file, tmp, sizeof(tmp)) < 0) 1980 control_file, tmp, sizeof(tmp)) < 0)
1976 { 1981 break;
1977 break ;
1978 }
1979 1982
1980 /* Obtain the dircache file entry cookie. */ 1983 /* Obtain the dircache file entry cookie. */
1981 dircache_search(DCS_CACHED_PATH | DCS_UPDATE_FILEREF, 1984 dircache_search(DCS_CACHED_PATH | DCS_UPDATE_FILEREF,
@@ -1985,19 +1988,26 @@ static void dc_thread_playlist(void)
1985 yield(); 1988 yield();
1986 } 1989 }
1987 1990
1991 /* If we indexed the whole playlist without being interrupted
1992 * then there are no dirty references; go to sleep. */
1993 if (index == playlist->amount)
1994 {
1995 is_dirty = false;
1996 sleep_time = TIMEOUT_BLOCK;
1997 logf("%s: scan complete", __func__);
1998 }
1999
1988 core_put_data_pinned(dcfrefs); 2000 core_put_data_pinned(dcfrefs);
1989 cancel_cpu_boost(); 2001 cancel_cpu_boost();
1990 2002
1991 if (index == playlist->amount) 2003 logf("%s: %ld ticks", __func__, current_tick - scan_start_tick);
1992 dc_has_dirty_pointers = false; 2004 break;
1993
1994 break ;
1995 } 2005 }
1996 2006
1997 case SYS_USB_CONNECTED: 2007 case SYS_USB_CONNECTED:
1998 usb_acknowledge(SYS_USB_CONNECTED_ACK); 2008 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1999 usb_wait_for_disconnect(&playlist_queue); 2009 usb_wait_for_disconnect(&playlist_queue);
2000 break ; 2010 break;
2001 } 2011 }
2002 } 2012 }
2003} 2013}
@@ -2098,6 +2108,8 @@ void playlist_init(void)
2098 queue_init(&playlist_queue, true); 2108 queue_init(&playlist_queue, true);
2099 queue_enable_queue_send(&playlist_queue, 2109 queue_enable_queue_send(&playlist_queue,
2100 &playlist_queue_sender_list, playlist_thread_id); 2110 &playlist_queue_sender_list, playlist_thread_id);
2111
2112 dc_thread_start(&current_playlist, false);
2101#endif /* HAVE_DIRCACHE */ 2113#endif /* HAVE_DIRCACHE */
2102} 2114}
2103 2115
@@ -2183,65 +2195,56 @@ int playlist_amount(void)
2183 * playlist off disk for viewing/editing. The index_buffer is used to store 2195 * playlist off disk for viewing/editing. The index_buffer is used to store
2184 * playlist indices (required for and only used if !current playlist). The 2196 * playlist indices (required for and only used if !current playlist). The
2185 * temp_buffer (if not NULL) is used as a scratchpad when loading indices. 2197 * temp_buffer (if not NULL) is used as a scratchpad when loading indices.
2198 *
2199 * XXX: This is really only usable by the playlist viewer. Never pass
2200 * playlist == NULL, that cannot and will not work.
2186 */ 2201 */
2187int playlist_create_ex(struct playlist_info* playlist, 2202int playlist_create_ex(struct playlist_info* playlist,
2188 const char* dir, const char* file, 2203 const char* dir, const char* file,
2189 void* index_buffer, int index_buffer_size, 2204 void* index_buffer, int index_buffer_size,
2190 void* temp_buffer, int temp_buffer_size) 2205 void* temp_buffer, int temp_buffer_size)
2191{ 2206{
2192 if (!playlist) 2207 /* Initialize playlist structure */
2193 { 2208 int r = rand() % 10;
2194 playlist = &current_playlist;
2195 playlist_mutex_lock(&(playlist->mutex));
2196 playlist->last_shuffled_start = playlist->amount;
2197 playlist_mutex_unlock(&(playlist->mutex));
2198 }
2199 else
2200 {
2201 /* Initialize playlist structure */
2202 int r = rand() % 10;
2203 2209
2204 /* Use random name for control file */ 2210 /* Use random name for control file */
2205 snprintf(playlist->control_filename, sizeof(playlist->control_filename), 2211 snprintf(playlist->control_filename, sizeof(playlist->control_filename),
2206 "%s.%d", PLAYLIST_CONTROL_FILE, r); 2212 "%s.%d", PLAYLIST_CONTROL_FILE, r);
2207 playlist->fd = -1; 2213 playlist->fd = -1;
2208 playlist->control_fd = -1; 2214 playlist->control_fd = -1;
2209 2215
2210 if (index_buffer) 2216 if (index_buffer)
2211 { 2217 {
2212 int num_indices = index_buffer_size / 2218 int num_indices = index_buffer_size /
2213 playlist_get_required_bufsz(playlist, false, 1); 2219 playlist_get_required_bufsz(playlist, false, 1);
2214 2220
2215 if (num_indices > global_settings.max_files_in_playlist) 2221 if (num_indices > global_settings.max_files_in_playlist)
2216 num_indices = global_settings.max_files_in_playlist; 2222 num_indices = global_settings.max_files_in_playlist;
2217 2223
2218 playlist->max_playlist_size = num_indices; 2224 playlist->max_playlist_size = num_indices;
2219 playlist->indices = index_buffer; 2225 playlist->indices = index_buffer;
2220#ifdef HAVE_DIRCACHE 2226#ifdef HAVE_DIRCACHE
2221 playlist->dcfrefs_handle = 0; 2227 playlist->dcfrefs_handle = 0;
2222#endif 2228#endif
2223 } 2229 }
2224 else 2230 else
2225 { 2231 {
2226 /* FIXME not sure if it's safe to share index buffers */ 2232 /* FIXME not sure if it's safe to share index buffers */
2227 playlist->max_playlist_size = current_playlist.max_playlist_size; 2233 playlist->max_playlist_size = current_playlist.max_playlist_size;
2228 playlist->indices = current_playlist.indices; 2234 playlist->indices = current_playlist.indices;
2229#ifdef HAVE_DIRCACHE 2235#ifdef HAVE_DIRCACHE
2230 playlist->dcfrefs_handle = 0; 2236 playlist->dcfrefs_handle = 0;
2231#endif 2237#endif
2232 }
2233
2234 chunk_alloc_free(&playlist->name_chunk_buffer);
2235 } 2238 }
2236 2239
2240 chunk_alloc_free(&playlist->name_chunk_buffer);
2241
2237 new_playlist_unlocked(playlist, dir, file); 2242 new_playlist_unlocked(playlist, dir, file);
2238 2243
2244 /* load the playlist file */
2239 if (file) 2245 if (file)
2240 {
2241 /* load the playlist file */
2242 add_indices_to_playlist(playlist, temp_buffer, temp_buffer_size); 2246 add_indices_to_playlist(playlist, temp_buffer, temp_buffer_size);
2243 dc_load_playlist_pointers(); 2247
2244 }
2245 return 0; 2248 return 0;
2246} 2249}
2247 2250
@@ -2251,6 +2254,10 @@ int playlist_create_ex(struct playlist_info* playlist,
2251int playlist_create(const char *dir, const char *file) 2254int playlist_create(const char *dir, const char *file)
2252{ 2255{
2253 struct playlist_info* playlist = &current_playlist; 2256 struct playlist_info* playlist = &current_playlist;
2257 int status = 0;
2258
2259 dc_thread_stop(playlist);
2260 playlist_mutex_lock(&playlist->mutex);
2254 2261
2255 new_playlist_unlocked(playlist, dir, file); 2262 new_playlist_unlocked(playlist, dir, file);
2256 2263
@@ -2266,18 +2273,20 @@ int playlist_create(const char *dir, const char *file)
2266 buflen = ALIGN_DOWN(buflen, 512); /* to avoid partial sector I/O */ 2273 buflen = ALIGN_DOWN(buflen, 512); /* to avoid partial sector I/O */
2267 /* load the playlist file */ 2274 /* load the playlist file */
2268 add_indices_to_playlist(playlist, buf, buflen); 2275 add_indices_to_playlist(playlist, buf, buflen);
2269 dc_load_playlist_pointers();
2270 core_free(handle); 2276 core_free(handle);
2271 } 2277 }
2272 else 2278 else
2273 { 2279 {
2274 /* should not happen -- happens if plugin takes audio buffer */ 2280 /* should not happen -- happens if plugin takes audio buffer */
2275 splashf(HZ * 2, "%s(): OOM", __func__); 2281 splashf(HZ * 2, "%s(): OOM", __func__);
2276 return -1; 2282 status = -1;
2277 } 2283 }
2278 } 2284 }
2279 2285
2280 return 0; 2286 playlist_mutex_unlock(&playlist->mutex);
2287 dc_thread_start(playlist, true);
2288
2289 return status;
2281} 2290}
2282 2291
2283/* Returns false if 'steps' is out of bounds, else true */ 2292/* Returns false if 'steps' is out of bounds, else true */
@@ -2331,18 +2340,24 @@ int playlist_delete(struct playlist_info* playlist, int index)
2331 if (!playlist) 2340 if (!playlist)
2332 playlist = &current_playlist; 2341 playlist = &current_playlist;
2333 2342
2343 dc_thread_stop(playlist);
2344 playlist_mutex_lock(&playlist->mutex);
2345
2334 if (check_control(playlist) < 0) 2346 if (check_control(playlist) < 0)
2335 { 2347 {
2336 notify_control_access_error(); 2348 notify_control_access_error();
2337 return -1; 2349 result = -1;
2350 goto out;
2338 } 2351 }
2339 2352
2340 dc_discard_playlist_pointers();
2341
2342 if (index == PLAYLIST_DELETE_CURRENT) 2353 if (index == PLAYLIST_DELETE_CURRENT)
2343 index = playlist->index; 2354 index = playlist->index;
2344 2355
2345 result = remove_track_from_playlist(playlist, index, true); 2356 result = remove_track_unlocked(playlist, index, true);
2357
2358out:
2359 playlist_mutex_unlock(&playlist->mutex);
2360 dc_thread_start(playlist, false);
2346 2361
2347 if (result != -1 && (audio_status() & AUDIO_STATUS_PLAY) && 2362 if (result != -1 && (audio_status() & AUDIO_STATUS_PLAY) &&
2348 playlist->started) 2363 playlist->started)
@@ -2607,10 +2622,14 @@ int playlist_insert_directory(struct playlist_info* playlist,
2607 if (!playlist) 2622 if (!playlist)
2608 playlist = &current_playlist; 2623 playlist = &current_playlist;
2609 2624
2625 dc_thread_stop(playlist);
2626 playlist_mutex_lock(&playlist->mutex);
2627
2610 if (check_control(playlist) < 0) 2628 if (check_control(playlist) < 0)
2611 { 2629 {
2612 notify_control_access_error(); 2630 notify_control_access_error();
2613 return -1; 2631 result = -1;
2632 goto out;
2614 } 2633 }
2615 2634
2616 if (position == PLAYLIST_REPLACE) 2635 if (position == PLAYLIST_REPLACE)
@@ -2618,11 +2637,12 @@ int playlist_insert_directory(struct playlist_info* playlist,
2618 if (playlist_remove_all_tracks(playlist) == 0) 2637 if (playlist_remove_all_tracks(playlist) == 0)
2619 position = PLAYLIST_INSERT_LAST; 2638 position = PLAYLIST_INSERT_LAST;
2620 else 2639 else
2621 return -1; 2640 {
2641 result = -1;
2642 goto out;
2643 }
2622 } 2644 }
2623 2645
2624 dc_discard_playlist_pointers();
2625
2626 if (queue) 2646 if (queue)
2627 count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT); 2647 count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT);
2628 else 2648 else
@@ -2646,11 +2666,13 @@ int playlist_insert_directory(struct playlist_info* playlist,
2646 2666
2647 display_playlist_count(context.count, count_str, true); 2667 display_playlist_count(context.count, count_str, true);
2648 2668
2669out:
2670 playlist_mutex_unlock(&playlist->mutex);
2671 dc_thread_start(playlist, true);
2672
2649 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) 2673 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
2650 audio_flush_and_reload_tracks(); 2674 audio_flush_and_reload_tracks();
2651 2675
2652 dc_load_playlist_pointers();
2653
2654 return result; 2676 return result;
2655} 2677}
2656 2678
@@ -2673,10 +2695,9 @@ int playlist_insert_playlist(struct playlist_info* playlist, const char *filenam
2673 if (!playlist) 2695 if (!playlist)
2674 playlist = &current_playlist; 2696 playlist = &current_playlist;
2675 2697
2698 dc_thread_stop(playlist);
2676 playlist_mutex_lock(&(playlist->mutex)); 2699 playlist_mutex_lock(&(playlist->mutex));
2677 2700
2678 dc_discard_playlist_pointers();
2679
2680 cpu_boost(true); 2701 cpu_boost(true);
2681 2702
2682 if (check_control(playlist) < 0) 2703 if (check_control(playlist) < 0)
@@ -2780,13 +2801,13 @@ int playlist_insert_playlist(struct playlist_info* playlist, const char *filenam
2780 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) 2801 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
2781 audio_flush_and_reload_tracks(); 2802 audio_flush_and_reload_tracks();
2782 2803
2783 dc_load_playlist_pointers();
2784 result = 0; 2804 result = 0;
2785 2805
2786out: 2806out:
2787 cpu_boost(false); 2807 cpu_boost(false);
2788 2808
2789 playlist_mutex_unlock(&(playlist->mutex)); 2809 playlist_mutex_unlock(&(playlist->mutex));
2810 dc_thread_start(playlist, true);
2790 2811
2791 return result; 2812 return result;
2792} 2813}
@@ -2803,10 +2824,9 @@ int playlist_insert_track(struct playlist_info* playlist, const char *filename,
2803 if (!playlist) 2824 if (!playlist)
2804 playlist = &current_playlist; 2825 playlist = &current_playlist;
2805 2826
2827 dc_thread_stop(playlist);
2806 playlist_mutex_lock(&(playlist->mutex)); 2828 playlist_mutex_lock(&(playlist->mutex));
2807 2829
2808 dc_discard_playlist_pointers();
2809
2810 if (check_control(playlist) < 0) 2830 if (check_control(playlist) < 0)
2811 { 2831 {
2812 notify_control_access_error(); 2832 notify_control_access_error();
@@ -2820,11 +2840,10 @@ int playlist_insert_track(struct playlist_info* playlist, const char *filename,
2820 * bunch of files from tagcache, syncing after every file wouldn't be 2840 * bunch of files from tagcache, syncing after every file wouldn't be
2821 * a good thing to do. */ 2841 * a good thing to do. */
2822 if (sync && result >= 0) 2842 if (sync && result >= 0)
2823 {
2824 playlist_sync(playlist); 2843 playlist_sync(playlist);
2825 }
2826 2844
2827 playlist_mutex_unlock(&(playlist->mutex)); 2845 playlist_mutex_unlock(&(playlist->mutex));
2846 dc_thread_start(playlist, true);
2828 2847
2829 return result; 2848 return result;
2830} 2849}
@@ -2867,12 +2886,13 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index)
2867 if (!playlist) 2886 if (!playlist)
2868 playlist = &current_playlist; 2887 playlist = &current_playlist;
2869 2888
2889 dc_thread_stop(playlist);
2870 playlist_mutex_lock(&(playlist->mutex)); 2890 playlist_mutex_lock(&(playlist->mutex));
2871 2891
2872 if (check_control(playlist) < 0) 2892 if (check_control(playlist) < 0)
2873 { 2893 {
2874 notify_control_access_error(); 2894 notify_control_access_error();
2875 goto out;; 2895 goto out;
2876 } 2896 }
2877 2897
2878 if (index == new_index) 2898 if (index == new_index)
@@ -2919,8 +2939,6 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index)
2919 goto out; 2939 goto out;
2920 } 2940 }
2921 2941
2922 dc_discard_playlist_pointers();
2923
2924 /* We want to insert the track at the position that was specified by 2942 /* We want to insert the track at the position that was specified by
2925 new_index. This may be different then new_index because of the 2943 new_index. This may be different then new_index because of the
2926 shifting that will occur after the delete. 2944 shifting that will occur after the delete.
@@ -2929,68 +2947,59 @@ int playlist_move(struct playlist_info* playlist, int index, int new_index)
2929 r = rotate_index(playlist, new_index); 2947 r = rotate_index(playlist, new_index);
2930 2948
2931 /* Delete track from original position */ 2949 /* Delete track from original position */
2932 result = remove_track_from_playlist(playlist, index, true); 2950 result = remove_track_unlocked(playlist, index, true);
2951 if (result == -1)
2952 goto out;
2933 2953
2934 if (result != -1) 2954 if (r == 0)/* First index */
2935 { 2955 {
2936 if (r == 0)/* First index */ 2956 new_index = PLAYLIST_PREPEND;
2937 { 2957 }
2938 new_index = PLAYLIST_PREPEND; 2958 else if (r == playlist->amount)
2939 } 2959 {
2940 else if (r == playlist->amount) 2960 /* Append */
2941 { 2961 new_index = PLAYLIST_INSERT_LAST;
2942 /* Append */ 2962 }
2943 new_index = PLAYLIST_INSERT_LAST; 2963 else /* Calculate index of desired position */
2944 } 2964 {
2945 else /* Calculate index of desired position */ 2965 new_index = (r+playlist->first_index)%playlist->amount;
2946 { 2966 }
2947 new_index = (r+playlist->first_index)%playlist->amount;
2948 }
2949
2950 result = add_track_to_playlist_unlocked(playlist, filename,
2951 new_index, queue, -1);
2952 2967
2953 if (result != -1) 2968 result = add_track_to_playlist_unlocked(playlist, filename,
2954 { 2969 new_index, queue, -1);
2955 if (current) 2970 if (result == -1)
2956 { 2971 goto out;
2957 /* Moved the current track */
2958 switch (new_index)
2959 {
2960 case PLAYLIST_PREPEND:
2961 playlist->index = playlist->first_index;
2962 break;
2963 case PLAYLIST_INSERT_LAST:
2964 playlist->index = playlist->first_index - 1;
2965 if (playlist->index < 0)
2966 playlist->index += playlist->amount;
2967 break;
2968 default:
2969 playlist->index = new_index;
2970 break;
2971 }
2972 }
2973 else if ((displace_current) && (new_index != PLAYLIST_PREPEND))
2974 {
2975 /* make the index point to the currently playing track */
2976 playlist->index++;
2977 }
2978 2972
2979 playlist_mutex_unlock(&(playlist->mutex)); 2973 if (current)
2980 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) 2974 {
2981 audio_flush_and_reload_tracks(); 2975 /* Moved the current track */
2982 } 2976 switch (new_index)
2983 else
2984 { 2977 {
2985 playlist_mutex_unlock(&(playlist->mutex)); 2978 case PLAYLIST_PREPEND:
2979 playlist->index = playlist->first_index;
2980 break;
2981 case PLAYLIST_INSERT_LAST:
2982 playlist->index = playlist->first_index - 1;
2983 if (playlist->index < 0)
2984 playlist->index += playlist->amount;
2985 break;
2986 default:
2987 playlist->index = new_index;
2988 break;
2986 } 2989 }
2987 } 2990 }
2988 2991 else if ((displace_current) && (new_index != PLAYLIST_PREPEND))
2989 dc_load_playlist_pointers(); 2992 {
2990 return result; 2993 /* make the index point to the currently playing track */
2994 playlist->index++;
2995 }
2991 2996
2992out: 2997out:
2993 playlist_mutex_unlock(&(playlist->mutex)); 2998 playlist_mutex_unlock(&(playlist->mutex));
2999 dc_thread_start(playlist, true);
3000
3001 if (result != -1 && playlist->started && (audio_status() & AUDIO_STATUS_PLAY))
3002 audio_flush_and_reload_tracks();
2994 3003
2995 return result; 3004 return result;
2996} 3005}
@@ -3024,7 +3033,8 @@ int playlist_next(int steps)
3024{ 3033{
3025 struct playlist_info* playlist = &current_playlist; 3034 struct playlist_info* playlist = &current_playlist;
3026 3035
3027 playlist_mutex_lock(&(playlist->mutex)); 3036 dc_thread_stop(playlist);
3037 playlist_mutex_lock(&playlist->mutex);
3028 3038
3029 int index; 3039 int index;
3030 3040
@@ -3036,8 +3046,6 @@ int playlist_next(int steps)
3036 { 3046 {
3037 int i, j; 3047 int i, j;
3038 3048
3039 dc_discard_playlist_pointers();
3040
3041 /* We need to delete all the queued songs */ 3049 /* We need to delete all the queued songs */
3042 for (i=0, j=steps; i<j; i++) 3050 for (i=0, j=steps; i<j; i++)
3043 { 3051 {
@@ -3045,7 +3053,7 @@ int playlist_next(int steps)
3045 3053
3046 if (index >= 0 && playlist->indices[index] & PLAYLIST_QUEUE_MASK) 3054 if (index >= 0 && playlist->indices[index] & PLAYLIST_QUEUE_MASK)
3047 { 3055 {
3048 remove_track_from_playlist(playlist, index, true); 3056 remove_track_unlocked(playlist, index, true);
3049 steps--; /* one less track */ 3057 steps--; /* one less track */
3050 } 3058 }
3051 } 3059 }
@@ -3062,7 +3070,7 @@ int playlist_next(int steps)
3062 /* Repeat shuffle mode. Re-shuffle playlist and resume play */ 3070 /* Repeat shuffle mode. Re-shuffle playlist and resume play */
3063 playlist->first_index = 0; 3071 playlist->first_index = 0;
3064 sort_playlist_unlocked(playlist, false, false); 3072 sort_playlist_unlocked(playlist, false, false);
3065 randomise_playlist(playlist, current_tick, false, true); 3073 randomise_playlist_unlocked(playlist, current_tick, false, true);
3066 3074
3067 playlist->started = true; 3075 playlist->started = true;
3068 playlist->index = 0; 3076 playlist->index = 0;
@@ -3071,9 +3079,7 @@ int playlist_next(int steps)
3071 else if (playlist->in_ram && global_settings.next_folder) 3079 else if (playlist->in_ram && global_settings.next_folder)
3072 { 3080 {
3073 /* we switch playlists here */ 3081 /* we switch playlists here */
3074 playlist_mutex_unlock(&(playlist->mutex));
3075 index = create_and_play_dir(steps, true); 3082 index = create_and_play_dir(steps, true);
3076 playlist_mutex_lock(&(playlist->mutex));
3077 if (index >= 0) 3083 if (index >= 0)
3078 { 3084 {
3079 playlist->index = index; 3085 playlist->index = index;
@@ -3110,7 +3116,8 @@ int playlist_next(int steps)
3110 } 3116 }
3111 3117
3112out: 3118out:
3113 playlist_mutex_unlock(&(playlist->mutex)); 3119 playlist_mutex_unlock(&playlist->mutex);
3120 dc_thread_start(playlist, true);
3114 3121
3115 return index; 3122 return index;
3116} 3123}
@@ -3179,7 +3186,11 @@ const char* playlist_peek(int steps, char* buf, size_t buf_size)
3179 return temp_ptr; 3186 return temp_ptr;
3180} 3187}
3181 3188
3182/* shuffle currently playing playlist */ 3189/*
3190 * shuffle currently playing playlist
3191 *
3192 * TODO: Merge this with playlist_shuffle()?
3193 */
3183int playlist_randomise(struct playlist_info* playlist, unsigned int seed, 3194int playlist_randomise(struct playlist_info* playlist, unsigned int seed,
3184 bool start_current) 3195 bool start_current)
3185{ 3196{
@@ -3188,12 +3199,12 @@ int playlist_randomise(struct playlist_info* playlist, unsigned int seed,
3188 if (!playlist) 3199 if (!playlist)
3189 playlist = &current_playlist; 3200 playlist = &current_playlist;
3190 3201
3202 dc_thread_stop(playlist);
3191 playlist_mutex_lock(&(playlist->mutex)); 3203 playlist_mutex_lock(&(playlist->mutex));
3192 3204
3193 check_control(playlist); 3205 check_control(playlist);
3194 3206
3195 result = randomise_playlist(playlist, seed, start_current, true); 3207 result = randomise_playlist_unlocked(playlist, seed, start_current, true);
3196
3197 if (result != -1 && (audio_status() & AUDIO_STATUS_PLAY) && 3208 if (result != -1 && (audio_status() & AUDIO_STATUS_PLAY) &&
3198 playlist->started) 3209 playlist->started)
3199 { 3210 {
@@ -3201,6 +3212,7 @@ int playlist_randomise(struct playlist_info* playlist, unsigned int seed,
3201 } 3212 }
3202 3213
3203 playlist_mutex_unlock(&(playlist->mutex)); 3214 playlist_mutex_unlock(&(playlist->mutex));
3215 dc_thread_start(playlist, true);
3204 3216
3205 return result; 3217 return result;
3206} 3218}
@@ -3208,6 +3220,8 @@ int playlist_randomise(struct playlist_info* playlist, unsigned int seed,
3208/* 3220/*
3209 * Removes all tracks, from the playlist, leaving the presently playing 3221 * Removes all tracks, from the playlist, leaving the presently playing
3210 * track queued. 3222 * track queued.
3223 *
3224 * TODO: This is insanely slow for huge playlists. Must fix.
3211 */ 3225 */
3212int playlist_remove_all_tracks(struct playlist_info *playlist) 3226int playlist_remove_all_tracks(struct playlist_info *playlist)
3213{ 3227{
@@ -3216,20 +3230,25 @@ int playlist_remove_all_tracks(struct playlist_info *playlist)
3216 if (playlist == NULL) 3230 if (playlist == NULL)
3217 playlist = &current_playlist; 3231 playlist = &current_playlist;
3218 3232
3219 dc_discard_playlist_pointers(); 3233 dc_thread_stop(playlist);
3234 playlist_mutex_lock(&playlist->mutex);
3220 3235
3221 while (playlist->index > 0) 3236 while (playlist->index > 0)
3222 if ((result = remove_track_from_playlist(playlist, 0, true)) < 0) 3237 if ((result = remove_track_unlocked(playlist, 0, true)) < 0)
3223 return result; 3238 goto out;
3224 3239
3225 while (playlist->amount > 1) 3240 while (playlist->amount > 1)
3226 if ((result = remove_track_from_playlist(playlist, 1, true)) < 0) 3241 if ((result = remove_track_unlocked(playlist, 1, true)) < 0)
3227 return result; 3242 goto out;
3228 3243
3229 if (playlist->amount == 1) { 3244 if (playlist->amount == 1) {
3230 playlist->indices[0] |= PLAYLIST_QUEUED; 3245 playlist->indices[0] |= PLAYLIST_QUEUED;
3231 } 3246 }
3232 3247
3248out:
3249 playlist_mutex_unlock(&playlist->mutex);
3250 dc_thread_start(playlist, false);
3251
3233 return 0; 3252 return 0;
3234} 3253}
3235 3254
@@ -3253,7 +3272,8 @@ int playlist_resume(void)
3253 splash(0, ID2P(LANG_WAIT)); 3272 splash(0, ID2P(LANG_WAIT));
3254 3273
3255 struct playlist_info* playlist = &current_playlist; 3274 struct playlist_info* playlist = &current_playlist;
3256 playlist_mutex_lock(&(playlist->mutex)); 3275 dc_thread_stop(playlist);
3276 playlist_mutex_lock(&playlist->mutex);
3257 3277
3258 if (core_allocatable() < (1 << 10)) 3278 if (core_allocatable() < (1 << 10))
3259 talk_buffer_set_policy(TALK_BUFFER_LOOSE); /* back off voice buffer */ 3279 talk_buffer_set_policy(TALK_BUFFER_LOOSE); /* back off voice buffer */
@@ -3437,8 +3457,7 @@ int playlist_resume(void)
3437 3457
3438 position = atoi(str1); 3458 position = atoi(str1);
3439 3459
3440 if (remove_track_from_playlist(playlist, position, 3460 if (remove_track_unlocked(playlist, position, false) < 0)
3441 false) < 0)
3442 { 3461 {
3443 result = -7; 3462 result = -7;
3444 goto out; 3463 goto out;
@@ -3467,7 +3486,7 @@ int playlist_resume(void)
3467 seed = atoi(str1); 3486 seed = atoi(str1);
3468 playlist->first_index = atoi(str2); 3487 playlist->first_index = atoi(str2);
3469 3488
3470 if (randomise_playlist(playlist, seed, false, 3489 if (randomise_playlist_unlocked(playlist, seed, false,
3471 false) < 0) 3490 false) < 0)
3472 { 3491 {
3473 result = -9; 3492 result = -9;
@@ -3647,10 +3666,9 @@ int playlist_resume(void)
3647 } 3666 }
3648 } 3667 }
3649 3668
3650 dc_load_playlist_pointers();
3651
3652out: 3669out:
3653 playlist_mutex_unlock(&(playlist->mutex)); 3670 playlist_mutex_unlock(&playlist->mutex);
3671 dc_thread_start(playlist, true);
3654 3672
3655 talk_buffer_set_policy(TALK_BUFFER_DEFAULT); 3673 talk_buffer_set_policy(TALK_BUFFER_DEFAULT);
3656 core_free(handle); 3674 core_free(handle);
@@ -3810,7 +3828,8 @@ int playlist_save(struct playlist_info* playlist, char *filename,
3810 { 3828 {
3811 strmemcpy(tmp_buf, path, pathlen); /* remove "_temp" */ 3829 strmemcpy(tmp_buf, path, pathlen); /* remove "_temp" */
3812 3830
3813 playlist_mutex_lock(&(playlist->mutex)); 3831 dc_thread_stop(playlist);
3832 playlist_mutex_lock(&playlist->mutex);
3814 3833
3815 if (!rename(path, tmp_buf)) 3834 if (!rename(path, tmp_buf))
3816 { 3835 {
@@ -3822,7 +3841,6 @@ int playlist_save(struct playlist_info* playlist, char *filename,
3822 close(playlist->fd); 3841 close(playlist->fd);
3823 playlist->fd = fd; 3842 playlist->fd = fd;
3824 fd = -1; 3843 fd = -1;
3825 dc_discard_playlist_pointers();
3826 3844
3827 if (!reparse) 3845 if (!reparse)
3828 { 3846 {
@@ -3848,11 +3866,11 @@ int playlist_save(struct playlist_info* playlist, char *filename,
3848 /* we need to recreate control because inserted tracks are 3866 /* we need to recreate control because inserted tracks are
3849 now part of the playlist and shuffle has been invalidated */ 3867 now part of the playlist and shuffle has been invalidated */
3850 result = recreate_control_unlocked(playlist); 3868 result = recreate_control_unlocked(playlist);
3851 dc_load_playlist_pointers();
3852 } 3869 }
3853 } 3870 }
3854 3871
3855 playlist_mutex_unlock(&(playlist->mutex)); 3872 playlist_mutex_unlock(&playlist->mutex);
3873 dc_thread_start(playlist, true);
3856 } 3874 }
3857 3875
3858 if (fd >= 0) 3876 if (fd >= 0)
@@ -3876,7 +3894,8 @@ int playlist_set_current(struct playlist_info* playlist)
3876 if (!playlist || (check_control(playlist) < 0)) 3894 if (!playlist || (check_control(playlist) < 0))
3877 return result; 3895 return result;
3878 3896
3879 playlist_mutex_lock(&(current_playlist.mutex)); 3897 dc_thread_stop(&current_playlist);
3898 playlist_mutex_lock(&current_playlist.mutex);
3880 3899
3881 empty_playlist_unlocked(&current_playlist, false); 3900 empty_playlist_unlocked(&current_playlist, false);
3882 3901
@@ -3927,7 +3946,8 @@ int playlist_set_current(struct playlist_info* playlist)
3927 result = 0; 3946 result = 0;
3928 3947
3929out: 3948out:
3930 playlist_mutex_unlock(&(current_playlist.mutex)); 3949 playlist_mutex_unlock(&current_playlist.mutex);
3950 dc_thread_start(&current_playlist, true);
3931 3951
3932 return result; 3952 return result;
3933} 3953}
@@ -3946,9 +3966,11 @@ void playlist_set_last_shuffled_start(void)
3946int playlist_shuffle(int random_seed, int start_index) 3966int playlist_shuffle(int random_seed, int start_index)
3947{ 3967{
3948 struct playlist_info* playlist = &current_playlist; 3968 struct playlist_info* playlist = &current_playlist;
3949 playlist_mutex_lock(&(playlist->mutex));
3950 bool start_current = false; 3969 bool start_current = false;
3951 3970
3971 dc_thread_stop(playlist);
3972 playlist_mutex_lock(&(playlist->mutex));
3973
3952 if (start_index >= 0 && global_settings.play_selected) 3974 if (start_index >= 0 && global_settings.play_selected)
3953 { 3975 {
3954 /* store the seek position before the shuffle */ 3976 /* store the seek position before the shuffle */
@@ -3956,8 +3978,11 @@ int playlist_shuffle(int random_seed, int start_index)
3956 start_current = true; 3978 start_current = true;
3957 } 3979 }
3958 3980
3959 randomise_playlist(playlist, random_seed, start_current, true); 3981 randomise_playlist_unlocked(playlist, random_seed, start_current, true);
3982
3960 playlist_mutex_unlock(&(playlist->mutex)); 3983 playlist_mutex_unlock(&(playlist->mutex));
3984 dc_thread_start(playlist, true);
3985
3961 return playlist->index; 3986 return playlist->index;
3962} 3987}
3963 3988
@@ -3993,7 +4018,8 @@ int playlist_sort(struct playlist_info* playlist, bool start_current)
3993 if (!playlist) 4018 if (!playlist)
3994 playlist = &current_playlist; 4019 playlist = &current_playlist;
3995 4020
3996 playlist_mutex_lock(&(playlist->mutex)); 4021 dc_thread_stop(playlist);
4022 playlist_mutex_lock(&playlist->mutex);
3997 4023
3998 check_control(playlist); 4024 check_control(playlist);
3999 result = sort_playlist_unlocked(playlist, start_current, true); 4025 result = sort_playlist_unlocked(playlist, start_current, true);
@@ -4001,7 +4027,8 @@ int playlist_sort(struct playlist_info* playlist, bool start_current)
4001 if (result != -1 && (audio_status() & AUDIO_STATUS_PLAY) && playlist->started) 4027 if (result != -1 && (audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
4002 audio_flush_and_reload_tracks(); 4028 audio_flush_and_reload_tracks();
4003 4029
4004 playlist_mutex_unlock(&(playlist->mutex)); 4030 playlist_mutex_unlock(&playlist->mutex);
4031 dc_thread_start(playlist, true);
4005 return result; 4032 return result;
4006} 4033}
4007 4034
@@ -4032,8 +4059,6 @@ void playlist_sync(struct playlist_info* playlist)
4032 sync_control(playlist, false); 4059 sync_control(playlist, false);
4033 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) 4060 if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started)
4034 audio_flush_and_reload_tracks(); 4061 audio_flush_and_reload_tracks();
4035
4036 dc_load_playlist_pointers();
4037} 4062}
4038 4063
4039/* Update resume info for current playing song. Returns -1 on error. */ 4064/* Update resume info for current playing song. Returns -1 on error. */