44 #define SCAN_THREADS 2
45 #define STATE_FILE "playlist-state"
47 #define ENTER pthread_mutex_lock (& mutex)
48 #define LEAVE pthread_mutex_unlock (& mutex)
50 #define LEAVE_RET_VOID do { \
51 pthread_mutex_unlock (& mutex); \
55 #define LEAVE_RET(ret) do { \
56 pthread_mutex_unlock (& mutex); \
60 #define DECLARE_PLAYLIST \
63 #define DECLARE_PLAYLIST_ENTRY \
64 Playlist * playlist; \
67 #define LOOKUP_PLAYLIST do { \
68 if (! (playlist = lookup_playlist (playlist_num))) \
72 #define LOOKUP_PLAYLIST_RET(ret) do { \
73 if (! (playlist = lookup_playlist (playlist_num))) \
77 #define LOOKUP_PLAYLIST_ENTRY do { \
79 if (! (entry = lookup_entry (playlist, entry_num))) \
83 #define LOOKUP_PLAYLIST_ENTRY_RET(ret) do { \
84 LOOKUP_PLAYLIST_RET(ret); \
85 if (! (entry = lookup_entry (playlist, entry_num))) \
89 #define SELECTION_HAS_CHANGED(p, a, c) \
90 queue_update (PLAYLIST_UPDATE_SELECTION, p, a, c)
92 #define METADATA_HAS_CHANGED(p, a, c) \
93 queue_update (PLAYLIST_UPDATE_METADATA, p, a, c)
95 #define PLAYLIST_HAS_CHANGED(p, a, c) \
96 queue_update (PLAYLIST_UPDATE_STRUCTURE, p, a, c)
107 char * formatted, *
title, * artist, * album;
134 static pthread_mutex_t
mutex = PTHREAD_MUTEX_INITIALIZER;
135 static pthread_cond_t
cond = PTHREAD_COND_INITIALIZER;
160 static void *
scanner (
void * unused);
186 entry->
tuple = tuple;
254 for (GList * node =
scan_queue.head; node; node = next)
259 if (item->
entry == entry)
268 if (scan_items[i] && scan_items[i]->entry == entry)
270 g_slice_free (
ScanItem, scan_items[i]);
271 scan_items[i] =
NULL;
313 g_slice_free (
Entry, entry);
319 GINT_TO_POINTER (preferred),
NULL,
NULL))
366 g_list_free (playlist->
queued);
372 for (
int count = 0; count < length; count ++)
375 playlist->
number = at + count;
387 for (
int count = 0; count < length; count ++)
390 entry->
number = at + count;
422 hook_call (
"playlist update", GINT_TO_POINTER (level));
480 int level = u->
level;
500 for (GList * node =
scan_queue.head; node; node = node->next)
503 if (item->
entry == entry)
509 if (scan_items[i] && scan_items[i]->entry == entry)
526 pthread_cond_broadcast (&
cond);
534 for (GList * node =
scan_queue.head; node; node = node->next)
543 if (scan_items[i] && scan_items[i]->
playlist == p)
596 int i = GPOINTER_TO_INT (data);
640 else if (need_tuple || ! decoder)
646 g_slice_free (
ScanItem, scan_items[i]);
647 scan_items[i] =
NULL;
649 pthread_cond_broadcast (&
cond);
660 pthread_cond_broadcast (&
cond);
672 if (! entry || entry->
failed)
675 if ((need_decoder && ! entry->
decoder) || (need_tuple && ! entry->
tuple))
693 if (! entry || entry->
failed)
696 if ((need_decoder && ! entry->
decoder) || (need_tuple && ! entry->
tuple))
732 pthread_cond_broadcast (&
cond);
747 active_playlist = playing_playlist =
NULL;
845 playing_playlist =
NULL;
857 int unique_id =
playlist->unique_id;
867 int num = p ? p->
number : -1;
967 int list = active_playlist ? active_playlist->
number : -1;
980 if (playlist_num < 0)
995 int list = playing_playlist ? playing_playlist->
number: -1;
1019 for (list = 0; list < count; list ++)
1077 if (at < 0 || at > entries)
1085 for (
int i = 0; i < number; i ++)
1105 for (
int count = 0; count < number; count ++)
1120 (playlist_num) < at + number)
1129 if (at < 0 || at > entries)
1131 if (number < 0 || number > entries - at)
1132 number = entries -
at;
1135 playlist->position->number < at + number)
1138 for (
int count = 0; count < number; count ++)
1188 Tuple * tuple = entry ? entry->
tuple :
NULL;
1207 char * * title,
char * * artist,
char * * album,
bool_t fast)
1224 int length = entry ? entry->
length : 0;
1238 if (entry_num == -1)
1249 hook_call (
"playlist position", GINT_TO_POINTER (playlist_num));
1270 if (
entry->selected == selected)
1273 entry->selected = selected;
1307 int selected_count =
playlist->selected_count;
1319 int first = entries, last = 0;
1321 for (
int count = 0; count < entries; count ++)
1328 first = MIN (first, entry->
number);
1335 playlist->selected_count = entries;
1344 if (first < entries)
1356 if (!
entry->selected || ! distance)
1360 int shift = 0, center, top, bottom;
1364 for (center = entry_num; center > 0 && shift > distance; )
1367 if (!
entry->selected)
1373 for (center = entry_num + 1; center < entries && shift < distance; )
1376 if (!
entry->selected)
1381 top = bottom = center;
1383 for (
int i = 0; i < top; i ++)
1386 if (
entry->selected)
1390 for (
int i = entries; i > bottom; i --)
1393 if (
entry->selected)
1399 for (
int i = top; i < center; i ++)
1402 if (!
entry->selected)
1406 for (
int i = top; i < bottom; i ++)
1409 if (
entry->selected)
1413 for (
int i = center; i < bottom; i ++)
1416 if (!
entry->selected)
1451 int before = 0, after = 0;
1454 for (
int count = 0; count < entries; count++)
1488 (
playlist->entries) - after - before);
1503 for (
int count = entries; count --; )
1522 for (
int i = 0; i < entries; i ++)
1524 int j = i + rand () % (entries - i);
1538 const Entry *
a = _a, *
b = _b;
1540 int diff = ((
int (*) (
const char *
a,
const char *
b)) compare)
1541 (a->filename, b->filename);
1547 return a->number - b->number;
1552 const Entry *
a = _a, *
b = _b;
1555 return b->tuple ? -1 : 0;
1559 int diff = ((
int (*) (
const Tuple *
a,
const Tuple *
b)) compare)
1560 (a->tuple, b->tuple);
1566 return a->number - b->number;
1571 const Entry *
a = _a, *
b = _b;
1573 int diff = ((
int (*) (
const char *
a,
const char *
b)) compare)
1574 (a->formatted ? a->formatted : a->filename,
1575 b->formatted ? b->formatted : b->filename);
1581 return a->number - b->number;
1585 const void *
b,
void * inner),
void * inner)
1594 a,
const void *
b,
void * inner),
void * inner)
1601 for (
int count = 0; count < entries; count++)
1611 for (
int count = 0; count < entries; count++)
1627 for (
int count = 0; count < entries; count ++)
1636 "metadata scanning is still in progress (or has been disabled)."));
1645 (
const char *
a,
const char *
b))
1657 (
const Tuple *
a,
const Tuple *
b))
1683 (
const char *
a,
const char *
b))
1695 (
const Tuple *
a,
const Tuple *
b))
1708 (
const char *
a,
const char *
b))
1733 for (
int count = 0; count < entries; count++)
1769 for (
int count = 0; count < entries; count ++)
1799 for (
int playlist_num = 0; playlist_num < num_playlists; playlist_num ++)
1804 for (
int entry_num = 0; entry_num < num_entries; entry_num ++)
1808 if (! strcmp (entry->
filename, filename))
1849 int count = g_list_length (playlist->
queued);
1881 int first = entries, last = 0;
1883 for (
int count = 0; count < entries; count++)
1891 playlist->
queued = g_list_append (playlist->
queued, entry);
1893 playlist->
queued = g_list_insert (playlist->
queued, entry, at++);
1896 first = MIN (first, entry->
number);
1900 if (first < entries)
1912 GList * node = g_list_nth (playlist->
queued, at);
1913 int entry_num = node ? ((
Entry *) node->data)->number : -1;
1936 int first = entries, last = 0;
1940 while (playlist->
queued && number --)
1944 first = MIN (first, entry->
number);
1947 playlist->
queued = g_list_delete_link (playlist->
queued,
1953 GList * anchor = g_list_nth (playlist->
queued, at - 1);
1957 while (anchor->next && number --)
1961 first = MIN (first, entry->
number);
1964 playlist->
queued = g_list_delete_link (playlist->
queued,
1970 if (first < entries)
1983 int first = entries, last = 0;
1985 for (GList * node = playlist->
queued; node; )
1987 GList * next = node->next;
1993 playlist->
queued = g_list_delete_link (playlist->
queued, node);
1994 first = MIN (first, entry->
number);
2001 if (first < entries)
2012 for (
int count = 0; count < entries; count ++)
2055 hook_call (
"playlist position", GINT_TO_POINTER (playlist_num));
2064 for (count = 0; count < entries; count ++)
2085 choice = rand () % choice;
2087 for (count = 0; ; count ++)
2110 for (
int count = 0; count < entries; count ++)
2169 hook_call (
"playlist position", GINT_TO_POINTER (playlist_num));
2178 int entry_num = entry ? entry->
number : -1;
2198 Tuple * tuple = entry ? entry->
tuple :
NULL;
2222 int length = entry->
length;
2230 if (! playing_playlist || ! playing_playlist->
position)
2244 if (! playing_playlist || ! playing_playlist->
position)
2254 if (! playing_playlist || ! playing_playlist->
position)
2271 FILE * handle = fopen (path,
"w");
2277 fprintf (handle,
"resume-time %d\n",
resume_time);
2279 fprintf (handle,
"active %d\n", active_playlist ? active_playlist->
number : -1);
2280 fprintf (handle,
"playing %d\n", playing_playlist ? playing_playlist->
number : -1);
2287 fprintf (handle,
"playlist %d\n", playlist_num);
2290 fprintf (handle,
"filename %s\n", playlist->
filename);
2292 fprintf (handle,
"position %d\n", playlist->
position ?
2307 if (! fgets (parse_key,
sizeof parse_key, handle))
2310 char * space = strchr (parse_key,
' ');
2315 parse_value = space + 1;
2317 char * newline = strchr (parse_value,
'\n');
2324 return (parse_value && ! strcmp (parse_key, key) && sscanf (parse_value,
2330 return (parse_value && ! strcmp (parse_key, key)) ?
str_get (parse_value) :
NULL;
2339 FILE * handle = fopen (path,
"r");
2364 while (
parse_integer (
"playlist", & playlist_num) && playlist_num >= 0 &&
2383 if (position >= 0 && position < entries)