diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/playlist.c | 467 |
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 |
195 | static bool dc_has_dirty_pointers = false; | ||
196 | 191 | ||
197 | static struct event_queue playlist_queue SHAREDBSS_ATTR; | 192 | static struct event_queue playlist_queue; |
198 | static struct queue_sender_list playlist_queue_sender_list SHAREDBSS_ATTR; | 193 | static struct queue_sender_list playlist_queue_sender_list; |
199 | static long playlist_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; | 194 | static long playlist_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; |
200 | static const char dc_thread_playlist_name[] = "playlist cachectrl"; | 195 | static 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 | ||
235 | static void dc_load_playlist_pointers(void) | 230 | static 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 == ¤t_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 | ||
243 | static void dc_discard_playlist_pointers(void) | 238 | static 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 == ¤t_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 | ||
253 | static void close_playlist_control_file(struct playlist_info *playlist) | 246 | static 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 | */ |
548 | static void empty_playlist_unlocked(struct playlist_info* playlist, bool resume) | 541 | static 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 | */ |
1559 | static int remove_track_from_playlist(struct playlist_info* playlist, | 1550 | static 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 | */ |
1645 | static int randomise_playlist(struct playlist_info* playlist, | 1633 | static 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(¤t_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 | */ |
2187 | int playlist_create_ex(struct playlist_info* playlist, | 2202 | int 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 = ¤t_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, | |||
2251 | int playlist_create(const char *dir, const char *file) | 2254 | int playlist_create(const char *dir, const char *file) |
2252 | { | 2255 | { |
2253 | struct playlist_info* playlist = ¤t_playlist; | 2256 | struct playlist_info* playlist = ¤t_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 = ¤t_playlist; | 2341 | playlist = ¤t_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 | |||
2358 | out: | ||
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 = ¤t_playlist; | 2623 | playlist = ¤t_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 | ||
2669 | out: | ||
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 = ¤t_playlist; | 2696 | playlist = ¤t_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 | ||
2786 | out: | 2806 | out: |
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 = ¤t_playlist; | 2825 | playlist = ¤t_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 = ¤t_playlist; | 2887 | playlist = ¤t_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 | ||
2992 | out: | 2997 | out: |
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 = ¤t_playlist; | 3034 | struct playlist_info* playlist = ¤t_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 | ||
3112 | out: | 3118 | out: |
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 | */ | ||
3183 | int playlist_randomise(struct playlist_info* playlist, unsigned int seed, | 3194 | int 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 = ¤t_playlist; | 3200 | playlist = ¤t_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 | */ |
3212 | int playlist_remove_all_tracks(struct playlist_info *playlist) | 3226 | int 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 = ¤t_playlist; | 3231 | playlist = ¤t_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 | ||
3248 | out: | ||
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 = ¤t_playlist; | 3274 | struct playlist_info* playlist = ¤t_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 | |||
3652 | out: | 3669 | out: |
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(¤t_playlist); |
3898 | playlist_mutex_lock(¤t_playlist.mutex); | ||
3880 | 3899 | ||
3881 | empty_playlist_unlocked(¤t_playlist, false); | 3900 | empty_playlist_unlocked(¤t_playlist, false); |
3882 | 3901 | ||
@@ -3927,7 +3946,8 @@ int playlist_set_current(struct playlist_info* playlist) | |||
3927 | result = 0; | 3946 | result = 0; |
3928 | 3947 | ||
3929 | out: | 3948 | out: |
3930 | playlist_mutex_unlock(&(current_playlist.mutex)); | 3949 | playlist_mutex_unlock(¤t_playlist.mutex); |
3950 | dc_thread_start(¤t_playlist, true); | ||
3931 | 3951 | ||
3932 | return result; | 3952 | return result; |
3933 | } | 3953 | } |
@@ -3946,9 +3966,11 @@ void playlist_set_last_shuffled_start(void) | |||
3946 | int playlist_shuffle(int random_seed, int start_index) | 3966 | int playlist_shuffle(int random_seed, int start_index) |
3947 | { | 3967 | { |
3948 | struct playlist_info* playlist = ¤t_playlist; | 3968 | struct playlist_info* playlist = ¤t_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 = ¤t_playlist; | 4019 | playlist = ¤t_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. */ |