Mercurial > audlegacy
annotate audacious/playlist.c @ 1588:15d92c51bde6 trunk
[svn] - modified time (mtime) has been introduced into tuple
- playlist makes use of mtime for scan control
- xspf records and reads mtime
author | yaz |
---|---|
date | Wed, 23 Aug 2006 07:46:33 -0700 |
parents | c073fd82ded6 |
children | 57676c0f2f33 |
rev | line source |
---|---|
0 | 1 /* BMP (C) GPL 2003 $top_src_dir/AUTHORS |
2 * | |
3 * based on: | |
4 * | |
5 * XMMS - Cross-platform multimedia player | |
6 * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, | |
7 * Thomas Nilsson and 4Front Technologies | |
8 * Copyright (C) 1999-2003 Haavard Kvaalen | |
9 * | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
1459 | 23 * Foundation, Inc., 59 Tmple Place - Suite 330, Boston, MA 02110-1301, USA. |
0 | 24 */ |
25 | |
26 #ifdef HAVE_CONFIG_H | |
27 # include "config.h" | |
28 #endif | |
29 | |
30 #include "playlist.h" | |
31 | |
32 #include <glib.h> | |
33 #include <glib/gprintf.h> | |
34 #include <stdlib.h> | |
35 #include <string.h> | |
36 #include <time.h> | |
37 | |
38 #include <unistd.h> | |
39 #include <sys/types.h> | |
40 #include <sys/stat.h> | |
41 #include <sys/errno.h> | |
42 | |
43 #include "input.h" | |
44 #include "main.h" | |
45 #include "mainwin.h" | |
46 #include "libaudacious/util.h" | |
47 #include "libaudacious/configdb.h" | |
48 #include "libaudacious/vfs.h" | |
49 #include "equalizer.h" | |
538
e4e897d20791
[svn] remove libaudcore, we never did anything with it
nenolod
parents:
418
diff
changeset
|
50 #include "playback.h" |
0 | 51 #include "playlist.h" |
1550 | 52 #include "playlist_container.h" |
383 | 53 #include "ui_playlist.h" |
0 | 54 #include "urldecode.h" |
55 #include "util.h" | |
1269 | 56 #include "ui_fileinfo.h" |
0 | 57 |
58 #include "debug.h" | |
59 | |
1251 | 60 typedef gint (*PlaylistCompareFunc) (PlaylistEntry * a, PlaylistEntry * b); |
0 | 61 typedef void (*PlaylistSaveFunc) (FILE * file); |
62 | |
63 PlaylistEntry *playlist_position; | |
64 G_LOCK_DEFINE(playlist); | |
65 | |
66 static GList *playlist = NULL; | |
67 static GList *shuffle_list = NULL; | |
68 static GList *queued_list = NULL; | |
69 | |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
70 /* If this is set to TRUE, we do not probe upon playlist add. |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
71 * |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
72 * Under Audacious 0.1.x, this was not a big deal because we used |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
73 * file extension introspection instead of looking for file format magic |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
74 * strings. |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
75 * |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
76 * Because we use file magic strings, we have to fstat a file being added |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
77 * to a playlist up to 1 * <number of input plugins installed> times. |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
78 * |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
79 * This can get really slow now that we're looking for files to add to a |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
80 * playlist. (Up to 5 minutes for 5000 songs, etcetera.) |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
81 * |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
82 * So, we obviously don't want to probe while opening a large playlist |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
83 * up. Hince the boolean below. |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
84 * |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
85 * January 7, 2006, William Pitcock <nenolod@nenolod.net> |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
86 */ |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
87 static gboolean loading_playlist = FALSE; |
0 | 88 |
89 G_LOCK_DEFINE(playlist_get_info_going); | |
90 | |
91 static gchar *playlist_current_name = NULL; | |
92 | |
93 static gboolean playlist_get_info_scan_active = FALSE; | |
94 static gboolean playlist_get_info_going = FALSE; | |
95 static GThread *playlist_get_info_thread; | |
96 | |
97 | |
98 static gint path_compare(const gchar * a, const gchar * b); | |
1251 | 99 static gint playlist_compare_path(PlaylistEntry * a, PlaylistEntry * b); |
100 static gint playlist_compare_filename(PlaylistEntry * a, PlaylistEntry * b); | |
101 static gint playlist_compare_title(PlaylistEntry * a, PlaylistEntry * b); | |
102 static gint playlist_compare_artist(PlaylistEntry * a, PlaylistEntry * b); | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
103 static time_t playlist_get_mtime(const gchar *filename); |
1251 | 104 static gint playlist_compare_date(PlaylistEntry * a, PlaylistEntry * b); |
1415 | 105 static gint playlist_compare_track(PlaylistEntry * a, PlaylistEntry * b); |
1430
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
106 static gint playlist_compare_playlist(PlaylistEntry * a, PlaylistEntry * b); |
1251 | 107 |
108 static gint playlist_dupscmp_path(PlaylistEntry * a, PlaylistEntry * b); | |
109 static gint playlist_dupscmp_filename(PlaylistEntry * a, PlaylistEntry * b); | |
110 static gint playlist_dupscmp_title(PlaylistEntry * a, PlaylistEntry * b); | |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
111 |
0 | 112 static PlaylistCompareFunc playlist_compare_func_table[] = { |
113 playlist_compare_path, | |
114 playlist_compare_filename, | |
115 playlist_compare_title, | |
1251 | 116 playlist_compare_artist, |
1415 | 117 playlist_compare_date, |
1430
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
118 playlist_compare_track, |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
119 playlist_compare_playlist |
0 | 120 }; |
121 | |
122 static guint playlist_load_ins(const gchar * filename, gint pos); | |
123 | |
124 static void playlist_generate_shuffle_list(void); | |
125 static void playlist_generate_shuffle_list_nolock(void); | |
126 | |
127 static void playlist_recalc_total_time_nolock(void); | |
128 static void playlist_recalc_total_time(void); | |
129 | |
130 | |
131 PlaylistEntry * | |
132 playlist_entry_new(const gchar * filename, | |
133 const gchar * title, | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
134 const gint length, |
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
135 InputPlugin * dec) |
0 | 136 { |
137 PlaylistEntry *entry; | |
138 | |
139 entry = g_new0(PlaylistEntry, 1); | |
140 entry->filename = g_strdup(filename); | |
141 entry->title = str_to_utf8(title); | |
142 entry->length = length; | |
143 entry->selected = FALSE; | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
144 entry->decoder = dec; |
0 | 145 |
146 return entry; | |
147 } | |
148 | |
149 void | |
150 playlist_entry_free(PlaylistEntry * entry) | |
151 { | |
152 if (!entry) | |
153 return; | |
154 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
155 if (entry->tuple != NULL) { |
1232 | 156 bmp_title_input_free(entry->tuple); |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
157 entry->tuple = NULL; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
158 } |
1232 | 159 |
160 if (entry->filename != NULL) | |
161 g_free(entry->filename); | |
162 | |
163 if (entry->title != NULL) | |
164 g_free(entry->title); | |
165 | |
0 | 166 g_free(entry); |
167 } | |
168 | |
169 static gboolean | |
170 playlist_entry_get_info(PlaylistEntry * entry) | |
171 { | |
1232 | 172 TitleInput *tuple; |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
173 time_t modtime = playlist_get_mtime(entry->filename); |
0 | 174 |
175 g_return_val_if_fail(entry != NULL, FALSE); | |
176 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
177 /* renew tuple if file mtime is newer than tuple mtime. */ |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
178 if(entry->tuple){ |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
179 if(entry->tuple->mtime == modtime) |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
180 return TRUE; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
181 else { |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
182 bmp_title_input_free(entry->tuple); |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
183 entry->tuple = NULL; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
184 } |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
185 } |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
186 |
1277
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
187 if (entry->decoder == NULL) |
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
188 entry->decoder = input_check_file(entry->filename, FALSE); |
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
189 |
1232 | 190 if (entry->decoder == NULL || entry->decoder->get_song_tuple == NULL) |
191 tuple = input_get_song_tuple(entry->filename); | |
192 else | |
193 tuple = entry->decoder->get_song_tuple(entry->filename); | |
194 | |
195 if (tuple == NULL) | |
0 | 196 return FALSE; |
197 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
198 /* attach mtime */ |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
199 tuple->mtime = modtime; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
200 |
0 | 201 /* entry is still around */ |
1356 | 202 entry->title = xmms_get_titlestring(tuple->formatter != NULL ? tuple->formatter : xmms_get_gentitle_format(), tuple); |
1232 | 203 entry->length = tuple->length; |
204 entry->tuple = tuple; | |
0 | 205 |
206 return TRUE; | |
207 } | |
208 | |
209 const gchar * | |
210 playlist_get_current_name(void) | |
211 { | |
212 return playlist_current_name; | |
213 } | |
214 | |
215 gboolean | |
216 playlist_set_current_name(const gchar * filename) | |
217 { | |
218 g_free(playlist_current_name); | |
219 | |
220 if (!filename) { | |
221 playlist_current_name = NULL; | |
222 return FALSE; | |
223 } | |
224 | |
225 playlist_current_name = g_strdup(filename); | |
226 return TRUE; | |
227 } | |
228 | |
229 static GList * | |
230 find_playlist_position_list(void) | |
231 { | |
232 REQUIRE_STATIC_LOCK(playlist); | |
233 | |
234 if (!playlist_position) { | |
235 if (cfg.shuffle) | |
236 return shuffle_list; | |
237 else | |
238 return playlist; | |
239 } | |
240 | |
241 if (cfg.shuffle) | |
242 return g_list_find(shuffle_list, playlist_position); | |
243 else | |
244 return g_list_find(playlist, playlist_position); | |
245 } | |
246 | |
247 static void | |
248 play_queued(void) | |
249 { | |
250 GList *tmp = queued_list; | |
251 | |
252 REQUIRE_STATIC_LOCK(playlist); | |
253 | |
254 playlist_position = queued_list->data; | |
255 queued_list = g_list_remove_link(queued_list, queued_list); | |
256 g_list_free_1(tmp); | |
257 } | |
258 | |
259 void | |
260 playlist_clear(void) | |
261 { | |
905 | 262 if (bmp_playback_get_playing()) { |
263 ip_data.stop = TRUE; | |
0 | 264 bmp_playback_stop(); |
905 | 265 ip_data.stop = FALSE; |
266 } | |
0 | 267 |
268 PLAYLIST_LOCK(); | |
269 | |
270 if (playlist) { | |
271 g_list_foreach(playlist, (GFunc) playlist_entry_free, NULL); | |
272 g_list_free(playlist); | |
273 | |
274 playlist = NULL; | |
275 playlist_position = NULL; | |
276 } | |
277 | |
278 PLAYLIST_UNLOCK(); | |
279 | |
280 playlist_generate_shuffle_list(); | |
281 playlistwin_update_list(); | |
282 playlist_recalc_total_time(); | |
283 } | |
284 | |
285 void | |
286 playlist_delete_node(GList * node, gboolean * set_info_text, | |
287 gboolean * restart_playing) | |
288 { | |
289 PlaylistEntry *entry; | |
290 GList *playing_song = NULL; | |
291 | |
292 REQUIRE_STATIC_LOCK(playlist); | |
293 | |
294 /* We call g_list_find manually here because we don't want an item | |
295 * in the shuffle_list */ | |
296 | |
297 if (playlist_position) | |
298 playing_song = g_list_find(playlist, playlist_position); | |
299 | |
300 entry = PLAYLIST_ENTRY(node->data); | |
301 | |
302 if (playing_song == node) { | |
303 *set_info_text = TRUE; | |
304 | |
305 if (bmp_playback_get_playing()) { | |
306 PLAYLIST_UNLOCK(); | |
905 | 307 ip_data.stop = TRUE; |
0 | 308 bmp_playback_stop(); |
905 | 309 ip_data.stop = FALSE; |
0 | 310 PLAYLIST_LOCK(); |
311 *restart_playing = TRUE; | |
312 } | |
313 | |
314 playing_song = find_playlist_position_list(); | |
315 | |
316 if (g_list_next(playing_song)) | |
317 playlist_position = g_list_next(playing_song)->data; | |
318 else if (g_list_previous(playing_song)) | |
319 playlist_position = g_list_previous(playing_song)->data; | |
320 else | |
321 playlist_position = NULL; | |
322 | |
323 /* Make sure the entry did not disappear under us */ | |
324 if (g_list_index(playlist_get(), entry) == -1) | |
325 return; | |
326 | |
327 } | |
328 else if (g_list_position(playlist, playing_song) > | |
329 g_list_position(playlist, node)) { | |
330 *set_info_text = TRUE; | |
331 } | |
332 | |
333 shuffle_list = g_list_remove(shuffle_list, entry); | |
334 playlist = g_list_remove_link(playlist, node); | |
335 playlist_entry_free(entry); | |
336 g_list_free_1(node); | |
337 | |
338 playlist_recalc_total_time_nolock(); | |
339 } | |
340 | |
341 void | |
342 playlist_delete_index(guint pos) | |
343 { | |
344 gboolean restart_playing = FALSE, set_info_text = FALSE; | |
345 GList *node; | |
346 | |
347 PLAYLIST_LOCK(); | |
348 | |
349 if (!playlist) { | |
350 PLAYLIST_UNLOCK(); | |
351 return; | |
352 } | |
353 | |
354 node = g_list_nth(playlist, pos); | |
355 | |
356 if (!node) { | |
357 PLAYLIST_UNLOCK(); | |
358 return; | |
359 } | |
360 | |
361 playlist_delete_node(node, &set_info_text, &restart_playing); | |
362 | |
363 PLAYLIST_UNLOCK(); | |
364 | |
365 playlist_recalc_total_time(); | |
366 | |
367 playlistwin_update_list(); | |
368 if (restart_playing) { | |
369 if (playlist_position) { | |
370 bmp_playback_initiate(); | |
371 } | |
372 else { | |
373 mainwin_clear_song_info(); | |
374 } | |
375 } | |
376 else if (set_info_text) { | |
377 mainwin_set_info_text(); | |
378 } | |
379 } | |
380 | |
381 void | |
382 playlist_delete_filenames(GList * filenames) | |
383 { | |
384 GList *node, *fnode; | |
385 gboolean set_info_text = FALSE, restart_playing = FALSE; | |
386 | |
387 PLAYLIST_LOCK(); | |
388 | |
389 for (fnode = filenames; fnode; fnode = g_list_next(fnode)) { | |
390 node = playlist; | |
391 | |
392 while (node) { | |
393 GList *next = g_list_next(node); | |
394 PlaylistEntry *entry = node->data; | |
395 | |
396 if (!strcmp(entry->filename, fnode->data)) | |
397 playlist_delete_node(node, &set_info_text, &restart_playing); | |
398 | |
399 node = next; | |
400 } | |
401 } | |
402 | |
403 playlist_recalc_total_time(); | |
404 PLAYLIST_UNLOCK(); | |
405 | |
406 playlistwin_update_list(); | |
407 | |
408 if (restart_playing) { | |
409 if (playlist_position) { | |
410 bmp_playback_initiate(); | |
411 } | |
412 else { | |
413 mainwin_clear_song_info(); | |
414 } | |
415 } | |
416 else if (set_info_text) { | |
417 mainwin_set_info_text(); | |
418 } | |
419 | |
420 } | |
421 | |
422 void | |
423 playlist_delete(gboolean crop) | |
424 { | |
425 gboolean restart_playing = FALSE, set_info_text = FALSE; | |
426 GList *node, *next_node; | |
427 PlaylistEntry *entry; | |
428 | |
429 PLAYLIST_LOCK(); | |
430 | |
431 node = playlist; | |
432 | |
433 while (node) { | |
434 entry = PLAYLIST_ENTRY(node->data); | |
435 | |
436 next_node = g_list_next(node); | |
437 | |
438 if ((entry->selected && !crop) || (!entry->selected && crop)) { | |
439 playlist_delete_node(node, &set_info_text, &restart_playing); | |
440 } | |
441 | |
442 node = next_node; | |
443 } | |
444 | |
445 PLAYLIST_UNLOCK(); | |
446 | |
447 playlist_recalc_total_time(); | |
448 | |
449 if (set_info_text) { | |
450 mainwin_set_info_text(); | |
451 } | |
452 | |
453 if (restart_playing) { | |
454 if (playlist_position) { | |
455 bmp_playback_initiate(); | |
456 } | |
457 else { | |
458 mainwin_clear_song_info(); | |
459 } | |
460 } | |
461 | |
462 playlistwin_update_list(); | |
463 } | |
464 | |
465 static void | |
466 __playlist_ins_with_info(const gchar * filename, | |
467 gint pos, | |
468 const gchar * title, | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
469 gint len, |
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
470 InputPlugin * dec) |
0 | 471 { |
472 g_return_if_fail(filename != NULL); | |
473 | |
474 PLAYLIST_LOCK(); | |
475 playlist = g_list_insert(playlist, | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
476 playlist_entry_new(filename, title, len, dec), |
0 | 477 pos); |
478 PLAYLIST_UNLOCK(); | |
479 | |
480 playlist_get_info_scan_active = TRUE; | |
481 } | |
482 | |
483 static void | |
1584 | 484 __playlist_ins_with_info_tuple(const gchar * filename, |
485 gint pos, | |
486 TitleInput *tuple, | |
487 InputPlugin * dec) | |
488 { | |
489 GList *node; | |
490 PlaylistEntry *entry; | |
491 | |
492 g_return_if_fail(filename != NULL); | |
493 | |
494 PLAYLIST_LOCK(); | |
495 playlist = g_list_insert(playlist, | |
496 playlist_entry_new(filename, tuple->track_name, tuple->length, dec), | |
497 pos); | |
498 | |
499 if(pos < 0 ) { | |
500 pos = g_list_length(playlist) - 1; /* last element. */ | |
501 } | |
502 | |
503 node = g_list_nth(playlist, pos); | |
504 entry = PLAYLIST_ENTRY(node->data); | |
505 | |
1587
c073fd82ded6
[svn] - Don't explode when loading http streams from xspf files.
nhjm449
parents:
1584
diff
changeset
|
506 if (tuple != NULL) { |
c073fd82ded6
[svn] - Don't explode when loading http streams from xspf files.
nhjm449
parents:
1584
diff
changeset
|
507 entry->title = xmms_get_titlestring(tuple->formatter != NULL ? tuple->formatter : xmms_get_gentitle_format(), tuple); |
c073fd82ded6
[svn] - Don't explode when loading http streams from xspf files.
nhjm449
parents:
1584
diff
changeset
|
508 entry->length = tuple->length; |
c073fd82ded6
[svn] - Don't explode when loading http streams from xspf files.
nhjm449
parents:
1584
diff
changeset
|
509 entry->tuple = tuple; |
c073fd82ded6
[svn] - Don't explode when loading http streams from xspf files.
nhjm449
parents:
1584
diff
changeset
|
510 } |
1584 | 511 |
512 PLAYLIST_UNLOCK(); | |
513 | |
514 playlist_get_info_scan_active = TRUE; | |
515 } | |
516 | |
517 static void | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
518 __playlist_ins(const gchar * filename, gint pos, InputPlugin *dec) |
0 | 519 { |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
520 __playlist_ins_with_info(filename, pos, NULL, -1, dec); |
0 | 521 playlist_recalc_total_time(); |
522 } | |
523 | |
524 gboolean | |
525 playlist_ins(const gchar * filename, gint pos) | |
526 { | |
527 gchar buf[64], *p; | |
528 gint r; | |
529 VFSFile *file; | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
530 InputPlugin *dec; |
0 | 531 |
532 if (is_playlist_name(filename)) { | |
533 playlist_load_ins(filename, pos); | |
534 return TRUE; | |
535 } | |
536 | |
1165 | 537 if (loading_playlist == TRUE || cfg.playlist_detect == TRUE) |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
538 dec = NULL; |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
539 else |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
540 dec = input_check_file(filename, TRUE); |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
541 |
1165 | 542 if (cfg.playlist_detect == TRUE || loading_playlist == TRUE || (loading_playlist == FALSE && dec != NULL)) |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
543 { |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
544 __playlist_ins(filename, pos, dec); |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
545 playlist_generate_shuffle_list(); |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
546 playlistwin_update_list(); |
0 | 547 return TRUE; |
548 } | |
549 | |
550 /* Some files (typically produced by some cgi-scripts) don't have | |
551 * the correct extension. Try to recognize these files by looking | |
552 * at their content. We only check for http entries since it does | |
553 * not make sense to have file entries in a playlist fetched from | |
554 * the net. */ | |
555 | |
556 /* Some strange people put fifo's with the .mp3 extension, so we | |
557 * need to make sure it's a real file (otherwise fread() may block | |
558 * and stall the entire program) */ | |
559 | |
560 /* FIXME: bah, FIFOs actually pass this regular file test */ | |
561 if (!vfs_file_test(filename, G_FILE_TEST_IS_REGULAR)) | |
562 return FALSE; | |
563 | |
564 if (!(file = vfs_fopen(filename, "rb"))) | |
565 return FALSE; | |
566 | |
567 r = vfs_fread(buf, 1, sizeof(buf), file); | |
568 vfs_fclose(file); | |
569 | |
570 for (p = buf; r-- > 0 && (*p == '\r' || *p == '\n'); p++); | |
571 | |
572 if (r > 5 && str_has_prefix_nocase(p, "http:")) { | |
573 playlist_load_ins(filename, pos); | |
574 return TRUE; | |
575 } | |
576 | |
577 return FALSE; | |
578 } | |
579 | |
580 /* FIXME: The next few functions are specific to Unix | |
581 * filesystems. Either abstract it away, or don't even bother checking | |
582 * at such low level */ | |
583 | |
584 typedef struct { | |
585 dev_t dev; | |
586 ino_t ino; | |
587 } DeviceInode; | |
588 | |
589 static DeviceInode * | |
590 devino_new(dev_t device, | |
591 ino_t inode) | |
592 { | |
593 DeviceInode *devino = g_new0(DeviceInode, 1); | |
594 | |
595 if (devino) | |
596 { | |
597 devino->dev = device; | |
598 devino->ino = inode; | |
599 } | |
600 | |
601 return devino; | |
602 } | |
603 | |
604 static guint | |
605 devino_hash(gconstpointer key) | |
606 { | |
607 const DeviceInode *d = key; | |
608 return d->ino; | |
609 } | |
610 | |
611 static gint | |
612 devino_compare(gconstpointer a, | |
613 gconstpointer b) | |
614 { | |
615 const DeviceInode *da = a, *db = b; | |
616 return (da->dev == db->dev && da->ino == db->ino); | |
617 } | |
618 | |
619 static gboolean | |
620 devino_destroy(gpointer key, | |
621 gpointer value, | |
622 gpointer data) | |
623 { | |
624 g_free(key); | |
625 return TRUE; | |
626 } | |
627 | |
628 static gboolean | |
629 file_is_hidden(const gchar * filename) | |
630 { | |
631 // FIXME: remove the const cast | |
632 g_return_val_if_fail(filename != NULL, FALSE); | |
633 return (g_basename((gchar *) filename)[0] == '.'); | |
634 } | |
635 | |
636 static GList * | |
637 playlist_dir_find_files(const gchar * path, | |
638 gboolean background, | |
639 GHashTable * htab) | |
640 { | |
641 GDir *dir; | |
642 GList *list = NULL, *ilist; | |
643 const gchar *dir_entry; | |
644 | |
645 struct stat statbuf; | |
646 DeviceInode *devino; | |
647 | |
648 if (!g_file_test(path, G_FILE_TEST_IS_DIR)) | |
649 return NULL; | |
650 | |
651 stat(path, &statbuf); | |
652 devino = devino_new(statbuf.st_dev, statbuf.st_ino); | |
653 | |
654 if (g_hash_table_lookup(htab, devino)) { | |
655 g_free(devino); | |
656 return NULL; | |
657 } | |
658 | |
659 g_hash_table_insert(htab, devino, GINT_TO_POINTER(1)); | |
660 | |
661 if ((ilist = input_scan_dir(path))) { | |
662 GList *node; | |
663 for (node = ilist; node; node = g_list_next(node)) { | |
664 gchar *name = g_build_filename(path, node->data, NULL); | |
665 list = g_list_prepend(list, name); | |
666 g_free(node->data); | |
667 } | |
668 g_list_free(ilist); | |
669 return list; | |
670 } | |
671 | |
672 if (!(dir = g_dir_open(path, 0, NULL))) | |
673 return NULL; | |
674 | |
675 while ((dir_entry = g_dir_read_name(dir))) { | |
676 gchar *filename; | |
677 | |
678 if (file_is_hidden(dir_entry)) | |
679 continue; | |
680 | |
681 filename = g_build_filename(path, dir_entry, NULL); | |
682 | |
683 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { | |
684 GList *sub; | |
685 sub = playlist_dir_find_files(filename, background, htab); | |
686 g_free(filename); | |
687 list = g_list_concat(list, sub); | |
688 } | |
1165 | 689 else if (cfg.playlist_detect == TRUE) |
690 list = g_list_prepend(list, filename); | |
0 | 691 else if (input_check_file(filename, TRUE)) |
692 list = g_list_prepend(list, filename); | |
693 else | |
694 g_free(filename); | |
695 | |
696 while (background && gtk_events_pending()) | |
697 gtk_main_iteration(); | |
698 } | |
699 g_dir_close(dir); | |
700 | |
701 return list; | |
702 } | |
703 | |
704 gboolean | |
705 playlist_add(const gchar * filename) | |
706 { | |
707 return playlist_ins(filename, -1); | |
708 } | |
709 | |
710 guint | |
711 playlist_add_dir(const gchar * directory) | |
712 { | |
713 return playlist_ins_dir(directory, -1, TRUE); | |
714 } | |
715 | |
716 guint | |
717 playlist_add_url(const gchar * url) | |
718 { | |
719 return playlist_ins_url(url, -1); | |
720 } | |
721 | |
722 guint | |
723 playlist_ins_dir(const gchar * path, | |
724 gint pos, | |
725 gboolean background) | |
726 { | |
727 guint entries = 0; | |
728 GList *list, *node; | |
729 GHashTable *htab; | |
730 | |
731 htab = g_hash_table_new(devino_hash, devino_compare); | |
732 | |
733 list = playlist_dir_find_files(path, background, htab); | |
734 list = g_list_sort(list, (GCompareFunc) path_compare); | |
735 | |
736 g_hash_table_foreach_remove(htab, devino_destroy, NULL); | |
737 | |
738 for (node = list; node; node = g_list_next(node)) { | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
739 __playlist_ins(node->data, pos, NULL); |
0 | 740 g_free(node->data); |
741 entries++; | |
742 if (pos >= 0) | |
743 pos++; | |
744 } | |
745 | |
746 g_list_free(list); | |
747 | |
748 playlist_recalc_total_time(); | |
749 playlist_generate_shuffle_list(); | |
750 playlistwin_update_list(); | |
751 return entries; | |
752 } | |
753 | |
754 guint | |
755 playlist_ins_url(const gchar * string, | |
756 gint pos) | |
757 { | |
758 gchar *tmp; | |
759 gint i = 1, entries = 0; | |
760 gboolean first = TRUE; | |
761 guint firstpos = 0; | |
762 gboolean success = FALSE; | |
763 gchar *decoded = NULL; | |
764 | |
765 g_return_val_if_fail(string != NULL, 0); | |
766 | |
767 playlistwin_update_list(); | |
768 | |
769 while (*string) { | |
770 GList *node; | |
771 tmp = strchr(string, '\n'); | |
772 if (tmp) { | |
773 if (*(tmp - 1) == '\r') | |
774 *(tmp - 1) = '\0'; | |
775 *tmp = '\0'; | |
776 } | |
777 | |
778 if (!(decoded = xmms_urldecode_path(string))) | |
779 decoded = g_strdup(string); | |
780 | |
781 if (g_file_test(decoded, G_FILE_TEST_IS_DIR)) { | |
782 i = playlist_ins_dir(decoded, pos, FALSE); | |
783 } | |
784 else { | |
785 if (is_playlist_name(decoded)) { | |
786 i = playlist_load_ins(decoded, pos); | |
787 } | |
788 else { | |
789 success = playlist_ins(decoded, pos); | |
790 i = 1; | |
791 } | |
792 } | |
793 | |
794 g_free(decoded); | |
795 | |
796 PLAYLIST_LOCK(); | |
797 node = g_list_nth(playlist_get(), pos); | |
798 PLAYLIST_UNLOCK(); | |
799 | |
800 entries += i; | |
801 | |
802 if (first) { | |
803 first = FALSE; | |
804 firstpos = pos; | |
805 } | |
806 | |
807 if (pos >= 0) | |
808 pos += i; | |
809 if (!tmp) | |
810 break; | |
811 | |
812 string = tmp + 1; | |
813 } | |
814 | |
815 playlist_recalc_total_time(); | |
816 playlist_generate_shuffle_list(); | |
817 playlistwin_update_list(); | |
818 | |
819 return entries; | |
820 } | |
821 | |
822 void | |
823 playlist_set_info(const gchar * title, gint length, gint rate, | |
824 gint freq, gint nch) | |
825 { | |
826 PLAYLIST_LOCK(); | |
827 | |
828 if (playlist_position) { | |
829 g_free(playlist_position->title); | |
830 playlist_position->title = g_strdup(title); | |
831 playlist_position->length = length; | |
832 } | |
833 | |
834 PLAYLIST_UNLOCK(); | |
835 | |
836 playlist_recalc_total_time(); | |
837 | |
838 mainwin_set_song_info(rate, freq, nch); | |
839 } | |
840 | |
841 void | |
842 playlist_check_pos_current(void) | |
843 { | |
844 gint pos, row, bottom; | |
845 | |
846 PLAYLIST_LOCK(); | |
847 if (!playlist || !playlist_position || !playlistwin_list) { | |
848 PLAYLIST_UNLOCK(); | |
849 return; | |
850 } | |
851 | |
852 pos = g_list_index(playlist, playlist_position); | |
853 | |
854 if (playlistwin_item_visible(pos)) { | |
855 PLAYLIST_UNLOCK(); | |
856 return; | |
857 } | |
858 | |
859 bottom = MAX(0, playlist_get_length_nolock() - | |
860 playlistwin_list->pl_num_visible); | |
861 row = CLAMP(pos - playlistwin_list->pl_num_visible / 2, 0, bottom); | |
862 PLAYLIST_UNLOCK(); | |
863 playlistwin_set_toprow(row); | |
864 } | |
865 | |
866 void | |
867 playlist_next(void) | |
868 { | |
869 GList *plist_pos_list; | |
870 gboolean restart_playing = FALSE; | |
871 | |
872 PLAYLIST_LOCK(); | |
873 if (!playlist) { | |
874 PLAYLIST_UNLOCK(); | |
875 return; | |
876 } | |
877 | |
878 plist_pos_list = find_playlist_position_list(); | |
879 | |
1026 | 880 if (!cfg.repeat && !g_list_next(plist_pos_list) && !queued_list) { |
0 | 881 PLAYLIST_UNLOCK(); |
882 return; | |
883 } | |
884 | |
885 if (bmp_playback_get_playing()) { | |
886 /* We need to stop before changing playlist_position */ | |
887 PLAYLIST_UNLOCK(); | |
895
1b919783797e
[svn] - should fix the ability to change songs while paused
nhjm449
parents:
853
diff
changeset
|
888 ip_data.stop = TRUE; |
0 | 889 bmp_playback_stop(); |
895
1b919783797e
[svn] - should fix the ability to change songs while paused
nhjm449
parents:
853
diff
changeset
|
890 ip_data.stop = FALSE; |
0 | 891 PLAYLIST_LOCK(); |
892 restart_playing = TRUE; | |
893 } | |
894 | |
895 plist_pos_list = find_playlist_position_list(); | |
896 if (queued_list) | |
897 play_queued(); | |
898 else if (g_list_next(plist_pos_list)) | |
899 playlist_position = g_list_next(plist_pos_list)->data; | |
900 else if (cfg.repeat) { | |
901 playlist_position = NULL; | |
902 playlist_generate_shuffle_list_nolock(); | |
903 if (cfg.shuffle) | |
904 playlist_position = shuffle_list->data; | |
905 else | |
906 playlist_position = playlist->data; | |
907 } | |
908 PLAYLIST_UNLOCK(); | |
909 playlist_check_pos_current(); | |
910 | |
911 if (restart_playing) | |
912 bmp_playback_initiate(); | |
913 else { | |
914 mainwin_set_info_text(); | |
915 playlistwin_update_list(); | |
916 } | |
917 } | |
918 | |
919 void | |
920 playlist_prev(void) | |
921 { | |
922 GList *plist_pos_list; | |
923 gboolean restart_playing = FALSE; | |
924 | |
925 PLAYLIST_LOCK(); | |
926 if (!playlist) { | |
927 PLAYLIST_UNLOCK(); | |
928 return; | |
929 } | |
930 | |
931 plist_pos_list = find_playlist_position_list(); | |
932 | |
933 if (!cfg.repeat && !g_list_previous(plist_pos_list)) { | |
934 PLAYLIST_UNLOCK(); | |
935 return; | |
936 } | |
937 | |
938 if (bmp_playback_get_playing()) { | |
939 /* We need to stop before changing playlist_position */ | |
940 PLAYLIST_UNLOCK(); | |
895
1b919783797e
[svn] - should fix the ability to change songs while paused
nhjm449
parents:
853
diff
changeset
|
941 ip_data.stop = TRUE; |
0 | 942 bmp_playback_stop(); |
895
1b919783797e
[svn] - should fix the ability to change songs while paused
nhjm449
parents:
853
diff
changeset
|
943 ip_data.stop = FALSE; |
0 | 944 PLAYLIST_LOCK(); |
945 restart_playing = TRUE; | |
946 } | |
947 | |
948 plist_pos_list = find_playlist_position_list(); | |
949 if (g_list_previous(plist_pos_list)) { | |
950 playlist_position = g_list_previous(plist_pos_list)->data; | |
951 } | |
952 else if (cfg.repeat) { | |
953 GList *node; | |
954 playlist_position = NULL; | |
955 playlist_generate_shuffle_list_nolock(); | |
956 if (cfg.shuffle) | |
957 node = g_list_last(shuffle_list); | |
958 else | |
959 node = g_list_last(playlist); | |
960 if (node) | |
961 playlist_position = node->data; | |
962 } | |
963 | |
964 PLAYLIST_UNLOCK(); | |
965 | |
966 playlist_check_pos_current(); | |
967 | |
968 if (restart_playing) | |
969 bmp_playback_initiate(); | |
970 else { | |
971 mainwin_set_info_text(); | |
972 playlistwin_update_list(); | |
973 } | |
974 } | |
975 | |
976 void | |
977 playlist_queue(void) | |
978 { | |
979 GList *list = playlist_get_selected(); | |
980 GList *it = list; | |
981 | |
982 PLAYLIST_LOCK(); | |
983 | |
984 while (it) { | |
985 GList *next = g_list_next(it); | |
986 GList *tmp; | |
987 | |
988 it->data = g_list_nth_data(playlist, GPOINTER_TO_INT(it->data)); | |
989 if ((tmp = g_list_find(queued_list, it->data))) { | |
990 queued_list = g_list_remove_link(queued_list, tmp); | |
991 g_list_free_1(tmp); | |
992 list = g_list_remove_link(list, it); | |
993 g_list_free_1(it); | |
994 } | |
995 | |
996 it = next; | |
997 } | |
998 | |
999 queued_list = g_list_concat(queued_list, list); | |
1000 | |
1001 PLAYLIST_UNLOCK(); | |
1002 | |
1003 playlist_recalc_total_time(); | |
1004 playlistwin_update_list(); | |
1005 } | |
1006 | |
1007 void | |
1008 playlist_queue_position(guint pos) | |
1009 { | |
1010 GList *tmp; | |
1011 PlaylistEntry *entry; | |
1012 | |
1013 PLAYLIST_LOCK(); | |
1014 entry = g_list_nth_data(playlist, pos); | |
1015 if ((tmp = g_list_find(queued_list, entry))) { | |
1016 queued_list = g_list_remove_link(queued_list, tmp); | |
1017 g_list_free_1(tmp); | |
1018 } | |
1019 else | |
1020 queued_list = g_list_append(queued_list, entry); | |
1021 PLAYLIST_UNLOCK(); | |
1022 | |
1023 playlist_recalc_total_time(); | |
1024 playlistwin_update_list(); | |
1025 } | |
1026 | |
1027 gboolean | |
1028 playlist_is_position_queued(guint pos) | |
1029 { | |
1030 PlaylistEntry *entry; | |
1031 GList *tmp; | |
1032 | |
1033 PLAYLIST_LOCK(); | |
1034 entry = g_list_nth_data(playlist, pos); | |
1035 tmp = g_list_find(queued_list, entry); | |
1036 PLAYLIST_UNLOCK(); | |
1037 | |
1038 return tmp != NULL; | |
1039 } | |
1040 | |
984 | 1041 gint |
1042 playlist_get_queue_position_number(guint pos) | |
1043 { | |
1044 PlaylistEntry *entry; | |
1045 gint tmp; | |
1046 | |
1047 PLAYLIST_LOCK(); | |
1048 entry = g_list_nth_data(playlist, pos); | |
1049 tmp = g_list_index(queued_list, entry); | |
1050 PLAYLIST_UNLOCK(); | |
1051 | |
1052 return tmp; | |
1053 } | |
1054 | |
1055 gint | |
1056 playlist_get_queue_qposition_number(guint pos) | |
1057 { | |
1058 PlaylistEntry *entry; | |
1059 gint tmp; | |
1060 | |
1061 PLAYLIST_LOCK(); | |
1062 entry = g_list_nth_data(queued_list, pos); | |
1063 tmp = g_list_index(playlist, entry); | |
1064 PLAYLIST_UNLOCK(); | |
1065 | |
1066 return tmp; | |
1067 } | |
1068 | |
0 | 1069 void |
1070 playlist_clear_queue(void) | |
1071 { | |
1072 PLAYLIST_LOCK(); | |
1073 g_list_free(queued_list); | |
1074 queued_list = NULL; | |
1075 PLAYLIST_UNLOCK(); | |
1076 | |
1077 playlist_recalc_total_time(); | |
1078 playlistwin_update_list(); | |
1079 } | |
1080 | |
1081 void | |
1082 playlist_queue_remove(guint pos) | |
1083 { | |
1084 void *entry; | |
1085 | |
1086 PLAYLIST_LOCK(); | |
1087 entry = g_list_nth_data(playlist, pos); | |
1088 queued_list = g_list_remove(queued_list, entry); | |
1089 PLAYLIST_UNLOCK(); | |
1090 | |
1091 playlistwin_update_list(); | |
1092 } | |
1093 | |
1094 gint | |
1095 playlist_get_queue_position(PlaylistEntry * entry) | |
1096 { | |
1097 return g_list_index(queued_list, entry); | |
1098 } | |
1099 | |
1100 void | |
1101 playlist_set_position(guint pos) | |
1102 { | |
1103 GList *node; | |
1104 gboolean restart_playing = FALSE; | |
1105 | |
1106 PLAYLIST_LOCK(); | |
1107 if (!playlist) { | |
1108 PLAYLIST_UNLOCK(); | |
1109 return; | |
1110 } | |
1111 | |
1112 node = g_list_nth(playlist, pos); | |
1113 if (!node) { | |
1114 PLAYLIST_UNLOCK(); | |
1115 return; | |
1116 } | |
1117 | |
1118 if (bmp_playback_get_playing()) { | |
1119 /* We need to stop before changing playlist_position */ | |
1120 PLAYLIST_UNLOCK(); | |
923 | 1121 ip_data.stop = TRUE; |
0 | 1122 bmp_playback_stop(); |
923 | 1123 ip_data.stop = FALSE; |
0 | 1124 PLAYLIST_LOCK(); |
1125 restart_playing = TRUE; | |
1126 } | |
1127 | |
1128 playlist_position = node->data; | |
1129 PLAYLIST_UNLOCK(); | |
1130 playlist_check_pos_current(); | |
1131 | |
1132 if (restart_playing) | |
1133 bmp_playback_initiate(); | |
1134 else { | |
1135 mainwin_set_info_text(); | |
1136 playlistwin_update_list(); | |
1137 } | |
1138 | |
1139 /* | |
1140 * Regenerate the shuffle list when the user set a position | |
1141 * manually | |
1142 */ | |
1143 playlist_generate_shuffle_list(); | |
1144 playlist_recalc_total_time(); | |
1145 } | |
1146 | |
1147 void | |
1148 playlist_eof_reached(void) | |
1149 { | |
1150 GList *plist_pos_list; | |
1151 | |
904
2cb51ff37e8d
[svn] - stop the psuedo output plugin when using 'no playlist advance' or 'stop after current song'
nhjm449
parents:
898
diff
changeset
|
1152 if ((cfg.no_playlist_advance && !cfg.repeat) || cfg.stopaftersong) |
2cb51ff37e8d
[svn] - stop the psuedo output plugin when using 'no playlist advance' or 'stop after current song'
nhjm449
parents:
898
diff
changeset
|
1153 ip_data.stop = TRUE; |
0 | 1154 bmp_playback_stop(); |
904
2cb51ff37e8d
[svn] - stop the psuedo output plugin when using 'no playlist advance' or 'stop after current song'
nhjm449
parents:
898
diff
changeset
|
1155 if ((cfg.no_playlist_advance && !cfg.repeat) || cfg.stopaftersong) |
2cb51ff37e8d
[svn] - stop the psuedo output plugin when using 'no playlist advance' or 'stop after current song'
nhjm449
parents:
898
diff
changeset
|
1156 ip_data.stop = FALSE; |
0 | 1157 |
1158 PLAYLIST_LOCK(); | |
1159 plist_pos_list = find_playlist_position_list(); | |
1160 | |
1161 if (cfg.no_playlist_advance) { | |
1162 PLAYLIST_UNLOCK(); | |
1163 mainwin_clear_song_info(); | |
1164 if (cfg.repeat) | |
1165 bmp_playback_initiate(); | |
1166 return; | |
1167 } | |
1168 | |
898 | 1169 if (cfg.stopaftersong) { |
1170 PLAYLIST_UNLOCK(); | |
1171 mainwin_clear_song_info(); | |
1172 mainwin_set_stopaftersong(FALSE); | |
1173 return; | |
1174 } | |
1175 | |
0 | 1176 if (queued_list) { |
1177 play_queued(); | |
1178 } | |
1179 else if (!g_list_next(plist_pos_list)) { | |
1180 if (cfg.shuffle) { | |
1181 playlist_position = NULL; | |
1182 playlist_generate_shuffle_list_nolock(); | |
1183 } | |
1184 else | |
1185 playlist_position = playlist->data; | |
1186 | |
1187 if (!cfg.repeat) { | |
1188 PLAYLIST_UNLOCK(); | |
1189 mainwin_clear_song_info(); | |
1190 mainwin_set_info_text(); | |
1191 return; | |
1192 } | |
1193 } | |
1194 else | |
1195 playlist_position = g_list_next(plist_pos_list)->data; | |
1196 | |
1197 PLAYLIST_UNLOCK(); | |
1198 | |
1199 playlist_check_pos_current(); | |
1200 bmp_playback_initiate(); | |
1201 mainwin_set_info_text(); | |
1202 playlistwin_update_list(); | |
1203 } | |
1204 | |
1205 gint | |
1206 playlist_get_length(void) | |
1207 { | |
1208 gint retval; | |
1209 | |
1210 PLAYLIST_LOCK(); | |
1211 retval = playlist_get_length_nolock(); | |
1212 PLAYLIST_UNLOCK(); | |
1213 | |
1214 return retval; | |
1215 } | |
1216 | |
1217 gint | |
1218 playlist_queue_get_length(void) | |
1219 { | |
1220 gint length; | |
1221 | |
1222 PLAYLIST_LOCK(); | |
1223 length = g_list_length(queued_list); | |
1224 PLAYLIST_UNLOCK(); | |
1225 | |
1226 return length; | |
1227 } | |
1228 | |
1229 gint | |
1230 playlist_get_length_nolock(void) | |
1231 { | |
1232 return g_list_length(playlist); | |
1233 } | |
1234 | |
1235 gchar * | |
1236 playlist_get_info_text(void) | |
1237 { | |
1238 gchar *text, *title, *numbers, *length; | |
1239 | |
1240 PLAYLIST_LOCK(); | |
1241 if (!playlist_position) { | |
1242 PLAYLIST_UNLOCK(); | |
1243 return NULL; | |
1244 } | |
1245 | |
1246 /* FIXME: there should not be a need to do additional conversion, | |
1247 * if playlist is properly maintained */ | |
1248 if (playlist_position->title) { | |
1249 title = str_to_utf8(playlist_position->title); | |
1250 } | |
1251 else { | |
1252 gchar *basename = g_path_get_basename(playlist_position->filename); | |
1253 title = filename_to_utf8(basename); | |
1254 g_free(basename); | |
1255 } | |
1256 | |
1257 /* | |
1258 * If the user don't want numbers in the playlist, don't | |
1259 * display them in other parts of XMMS | |
1260 */ | |
1261 | |
1262 if (cfg.show_numbers_in_pl) | |
1263 numbers = g_strdup_printf("%d. ", playlist_get_position_nolock() + 1); | |
1264 else | |
1265 numbers = g_strdup(""); | |
1266 | |
1267 if (playlist_position->length != -1) | |
1268 length = g_strdup_printf(" (%d:%-2.2d)", | |
1269 playlist_position->length / 60000, | |
1270 (playlist_position->length / 1000) % 60); | |
1271 else | |
1272 length = g_strdup(""); | |
1273 | |
1274 PLAYLIST_UNLOCK(); | |
1275 | |
1276 text = convert_title_text(g_strconcat(numbers, title, length, NULL)); | |
1277 | |
1278 g_free(numbers); | |
1279 g_free(title); | |
1280 g_free(length); | |
1281 | |
1282 return text; | |
1283 } | |
1284 | |
1285 gint | |
1286 playlist_get_current_length(void) | |
1287 { | |
1288 gint len = 0; | |
1289 | |
1290 PLAYLIST_LOCK(); | |
1291 if (playlist && playlist_position) | |
1292 len = playlist_position->length; | |
1293 PLAYLIST_UNLOCK(); | |
1294 | |
1295 return len; | |
1296 } | |
1297 | |
1298 gboolean | |
1553 | 1299 playlist_save(const gchar * filename) |
0 | 1300 { |
1553 | 1301 PlaylistContainer *plc = NULL; |
1302 gchar *ext; | |
0 | 1303 |
1304 g_return_val_if_fail(filename != NULL, FALSE); | |
1305 | |
1553 | 1306 ext = strrchr(filename, '.') + 1; |
1307 | |
0 | 1308 playlist_set_current_name(filename); |
1309 | |
1553 | 1310 if ((plc = playlist_container_find(ext)) == NULL) |
0 | 1311 return FALSE; |
1312 | |
1555 | 1313 if (plc->plc_write == NULL) |
1314 return FALSE; | |
1315 | |
1553 | 1316 plc->plc_write(filename, 0); |
1317 | |
1318 return TRUE; | |
0 | 1319 } |
1320 | |
1321 gboolean | |
1322 playlist_load(const gchar * filename) | |
1323 { | |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1324 gboolean ret = FALSE; |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1325 |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1326 loading_playlist = TRUE; |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1327 ret = playlist_load_ins(filename, -1); |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1328 loading_playlist = FALSE; |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1329 |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1330 return ret; |
0 | 1331 } |
1332 | |
1554 | 1333 void |
0 | 1334 playlist_load_ins_file(const gchar * filename_p, |
1335 const gchar * playlist_name, gint pos, | |
1336 const gchar * title, gint len) | |
1337 { | |
1338 gchar *filename; | |
1339 gchar *tmp, *path; | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
1340 InputPlugin *dec; /* for decoder cache */ |
0 | 1341 |
1342 g_return_if_fail(filename_p != NULL); | |
1343 g_return_if_fail(playlist_name != NULL); | |
1344 | |
633
bf9bc9a514ba
[svn] Use g_strchug instead of g_strstrip during playlist load. Trailing whitespace can be a valid occurance. Closes bug #282.
chainsaw
parents:
538
diff
changeset
|
1345 filename = g_strchug(g_strdup(filename_p)); |
0 | 1346 |
944
03d141f44b4d
[svn] Convert \ path separators to /. Support was already present, but was not enabled before. Closes bug #461.
chainsaw
parents:
923
diff
changeset
|
1347 while ((tmp = strchr(filename, '\\')) != NULL) |
03d141f44b4d
[svn] Convert \ path separators to /. Support was already present, but was not enabled before. Closes bug #461.
chainsaw
parents:
923
diff
changeset
|
1348 *tmp = '/'; |
0 | 1349 |
1350 if (filename[0] != '/' && !strstr(filename, "://")) { | |
1351 path = g_strdup(playlist_name); | |
1352 if ((tmp = strrchr(path, '/'))) | |
1353 *tmp = '\0'; | |
1354 else { | |
1163
ff71f891265b
[svn] - Allow to do format detection on demand; instead of immediately on add
nenolod
parents:
1026
diff
changeset
|
1355 if (loading_playlist != TRUE || cfg.playlist_detect == FALSE) |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1356 dec = input_check_file(filename, FALSE); |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1357 else |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1358 dec = NULL; |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1359 |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
1360 __playlist_ins_with_info(filename, pos, title, len, dec); |
0 | 1361 return; |
1362 } | |
1363 tmp = g_build_filename(path, filename, NULL); | |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1364 |
1165 | 1365 if (loading_playlist != TRUE && cfg.playlist_detect != TRUE) |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1366 dec = input_check_file(tmp, FALSE); |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1367 else |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1368 dec = NULL; |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1369 |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
1370 __playlist_ins_with_info(tmp, pos, title, len, dec); |
0 | 1371 g_free(tmp); |
1372 g_free(path); | |
1373 } | |
1374 else | |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
1375 { |
1165 | 1376 if (loading_playlist != TRUE && cfg.playlist_detect != TRUE) |
397
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1377 dec = input_check_file(filename, FALSE); |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1378 else |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1379 dec = NULL; |
4fa1244ad483
[svn] Do not generate a cache when loading a playlist.
nenolod
parents:
383
diff
changeset
|
1380 |
355
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
1381 __playlist_ins_with_info(filename, pos, title, len, dec); |
1c701dfe5098
[svn] Cache the decoder used for each PlaylistEntry. This reduces the amount
nenolod
parents:
284
diff
changeset
|
1382 } |
0 | 1383 |
1384 g_free(filename); | |
1385 } | |
1386 | |
1584 | 1387 void |
1388 playlist_load_ins_file_tuple(const gchar * filename_p, | |
1389 const gchar * playlist_name, | |
1390 gint pos, | |
1391 TitleInput *tuple) | |
1392 { | |
1393 gchar *filename; | |
1394 gchar *tmp, *path; | |
1395 InputPlugin *dec; /* for decoder cache */ | |
1396 | |
1397 g_return_if_fail(filename_p != NULL); | |
1398 g_return_if_fail(playlist_name != NULL); | |
1399 | |
1400 filename = g_strchug(g_strdup(filename_p)); | |
1401 | |
1402 while ((tmp = strchr(filename, '\\')) != NULL) | |
1403 *tmp = '/'; | |
1404 | |
1405 if (filename[0] != '/' && !strstr(filename, "://")) { | |
1406 path = g_strdup(playlist_name); | |
1407 if ((tmp = strrchr(path, '/'))) | |
1408 *tmp = '\0'; | |
1409 else { | |
1410 if (loading_playlist != TRUE || cfg.playlist_detect == FALSE) | |
1411 dec = input_check_file(filename, FALSE); | |
1412 else | |
1413 dec = NULL; | |
1414 | |
1415 __playlist_ins_with_info_tuple(filename, pos, tuple, dec); | |
1416 return; | |
1417 } | |
1418 tmp = g_build_filename(path, filename, NULL); | |
1419 | |
1420 if (loading_playlist != TRUE && cfg.playlist_detect != TRUE) | |
1421 dec = input_check_file(tmp, FALSE); | |
1422 else | |
1423 dec = NULL; | |
1424 | |
1425 __playlist_ins_with_info_tuple(tmp, pos, tuple, dec); | |
1426 g_free(tmp); | |
1427 g_free(path); | |
1428 } | |
1429 else | |
1430 { | |
1431 if (loading_playlist != TRUE && cfg.playlist_detect != TRUE) | |
1432 dec = input_check_file(filename, FALSE); | |
1433 else | |
1434 dec = NULL; | |
1435 | |
1436 __playlist_ins_with_info_tuple(filename, pos, tuple, dec); | |
1437 } | |
1438 | |
1439 g_free(filename); | |
1440 } | |
1441 | |
0 | 1442 static guint |
1443 playlist_load_ins(const gchar * filename, gint pos) | |
1444 { | |
1554 | 1445 PlaylistContainer *plc; |
1446 gchar *ext; | |
0 | 1447 |
1448 g_return_val_if_fail(filename != NULL, 0); | |
1449 | |
1554 | 1450 ext = strrchr(filename, '.') + 1; |
1451 plc = playlist_container_find(ext); | |
1452 | |
1453 g_return_val_if_fail(plc != NULL, 0); | |
1454 g_return_val_if_fail(plc->plc_read != NULL, 0); | |
1455 | |
1560
5840d797ea02
[svn] - hmm, calling plc->load() might be a good idea!
nenolod
parents:
1559
diff
changeset
|
1456 plc->plc_read(filename, pos); |
5840d797ea02
[svn] - hmm, calling plc->load() might be a good idea!
nenolod
parents:
1559
diff
changeset
|
1457 |
1554 | 1458 playlist_generate_shuffle_list(); |
1459 playlistwin_update_list(); | |
1460 | |
1461 return 1; | |
0 | 1462 } |
1463 | |
1464 GList * | |
1465 get_playlist_nth(guint nth) | |
1466 { | |
1467 REQUIRE_STATIC_LOCK(playlist); | |
1468 return g_list_nth(playlist, nth); | |
1469 } | |
1470 | |
1471 | |
1472 GList * | |
1473 playlist_get(void) | |
1474 { | |
1475 REQUIRE_STATIC_LOCK(playlist); | |
1476 return playlist; | |
1477 } | |
1478 | |
1479 gint | |
1480 playlist_get_position_nolock(void) | |
1481 { | |
1482 if (playlist && playlist_position) | |
1483 return g_list_index(playlist, playlist_position); | |
1484 return 0; | |
1485 } | |
1486 | |
1487 gint | |
1488 playlist_get_position(void) | |
1489 { | |
1490 gint pos; | |
1491 | |
1492 PLAYLIST_LOCK(); | |
1493 pos = playlist_get_position_nolock(); | |
1494 PLAYLIST_UNLOCK(); | |
1495 | |
1496 return pos; | |
1497 } | |
1498 | |
1499 gchar * | |
1500 playlist_get_filename(guint pos) | |
1501 { | |
1502 gchar *filename; | |
1503 PlaylistEntry *entry; | |
1504 GList *node; | |
1505 | |
1506 PLAYLIST_LOCK(); | |
1507 if (!playlist) { | |
1508 PLAYLIST_UNLOCK(); | |
1509 return NULL; | |
1510 } | |
1511 node = g_list_nth(playlist, pos); | |
1512 if (!node) { | |
1513 PLAYLIST_UNLOCK(); | |
1514 return NULL; | |
1515 } | |
1516 entry = node->data; | |
1517 | |
1518 filename = g_strdup(entry->filename); | |
1519 PLAYLIST_UNLOCK(); | |
1520 | |
1521 return filename; | |
1522 } | |
1523 | |
1524 gchar * | |
1525 playlist_get_songtitle(guint pos) | |
1526 { | |
1527 gchar *title = NULL; | |
1528 PlaylistEntry *entry; | |
1529 GList *node; | |
1530 | |
1531 PLAYLIST_LOCK(); | |
1532 | |
1533 if (!playlist) { | |
1534 PLAYLIST_UNLOCK(); | |
1535 return NULL; | |
1536 } | |
1537 | |
1538 if (!(node = g_list_nth(playlist, pos))) { | |
1539 PLAYLIST_UNLOCK(); | |
1540 return NULL; | |
1541 } | |
1542 | |
1543 entry = node->data; | |
1544 | |
1545 /* FIXME: simplify this logic */ | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1546 // if (!entry->title && entry->length == -1) { |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1547 if ( (!entry->title && entry->length == -1) || |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1548 (entry->tuple && (entry->tuple->mtime != playlist_get_mtime(entry->filename))) ){ |
0 | 1549 if (playlist_entry_get_info(entry)) |
1550 title = entry->title; | |
1551 } | |
1552 else { | |
1553 title = entry->title; | |
1554 } | |
1555 | |
1556 PLAYLIST_UNLOCK(); | |
1557 | |
1558 if (!title) { | |
1559 title = g_path_get_basename(entry->filename); | |
1560 return str_replace(title, filename_to_utf8(title)); | |
1561 } | |
1562 | |
1563 return str_to_utf8(title); | |
1564 } | |
1565 | |
1235 | 1566 TitleInput * |
1567 playlist_get_tuple(guint pos) | |
1568 { | |
1569 PlaylistEntry *entry; | |
1570 TitleInput *tuple = NULL; | |
1571 GList *node; | |
1572 | |
1573 PLAYLIST_LOCK(); | |
1574 | |
1575 if (!playlist) { | |
1576 PLAYLIST_UNLOCK(); | |
1577 return NULL; | |
1578 } | |
1579 | |
1580 if (!(node = g_list_nth(playlist, pos))) { | |
1581 PLAYLIST_UNLOCK(); | |
1582 return NULL; | |
1583 } | |
1584 | |
1585 entry = (PlaylistEntry *) node->data; | |
1586 | |
1587 tuple = entry->tuple; | |
1588 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1589 // if no tuple or tuple with old mtime, get new one. |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1590 if (!tuple || (entry->tuple->mtime != playlist_get_mtime(entry->filename))) { |
1237
17630223d25b
[svn] - if a PlaylistEntry does not have a cached tuple, generate it on demand.
nenolod
parents:
1235
diff
changeset
|
1591 playlist_entry_get_info(entry); |
17630223d25b
[svn] - if a PlaylistEntry does not have a cached tuple, generate it on demand.
nenolod
parents:
1235
diff
changeset
|
1592 tuple = entry->tuple; |
17630223d25b
[svn] - if a PlaylistEntry does not have a cached tuple, generate it on demand.
nenolod
parents:
1235
diff
changeset
|
1593 } |
17630223d25b
[svn] - if a PlaylistEntry does not have a cached tuple, generate it on demand.
nenolod
parents:
1235
diff
changeset
|
1594 |
1235 | 1595 PLAYLIST_UNLOCK(); |
1596 | |
1597 return tuple; | |
1598 } | |
1599 | |
0 | 1600 gint |
1601 playlist_get_songtime(guint pos) | |
1602 { | |
1603 gint song_time = -1; | |
1604 PlaylistEntry *entry; | |
1605 GList *node; | |
1606 | |
1607 PLAYLIST_LOCK(); | |
1608 | |
1609 if (!playlist) { | |
1610 PLAYLIST_UNLOCK(); | |
1611 return -1; | |
1612 } | |
1613 | |
1614 if (!(node = g_list_nth(playlist, pos))) { | |
1615 PLAYLIST_UNLOCK(); | |
1616 return -1; | |
1617 } | |
1618 | |
1619 entry = node->data; | |
1620 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1621 // if (!entry->title && entry->length == -1) { |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1622 if (!entry->tuple || (entry->tuple->mtime != playlist_get_mtime(entry->filename))){ |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1623 |
0 | 1624 if (playlist_entry_get_info(entry)) |
1625 song_time = entry->length; | |
1626 | |
1627 PLAYLIST_UNLOCK(); | |
1628 } | |
1629 else { | |
1630 song_time = entry->length; | |
1631 PLAYLIST_UNLOCK(); | |
1632 } | |
1633 | |
1634 return song_time; | |
1635 } | |
1636 | |
1637 static gint | |
1415 | 1638 playlist_compare_track(PlaylistEntry * a, |
1639 PlaylistEntry * b) | |
1640 { | |
1641 g_return_val_if_fail(a != NULL, 0); | |
1642 g_return_val_if_fail(b != NULL, 0); | |
1643 | |
1644 g_return_val_if_fail(a->tuple != NULL, 0); | |
1645 g_return_val_if_fail(b->tuple != NULL, 0); | |
1646 | |
1647 return (a->tuple->track_number - b->tuple->track_number); | |
1648 } | |
1649 | |
1650 static gint | |
1430
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1651 playlist_compare_playlist(PlaylistEntry * a, |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1652 PlaylistEntry * b) |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1653 { |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1654 const gchar *a_title = NULL, *b_title = NULL; |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1655 |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1656 g_return_val_if_fail(a != NULL, 0); |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1657 g_return_val_if_fail(b != NULL, 0); |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1658 |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1659 if (a->title != NULL) |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1660 a_title = a->title; |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1661 else { |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1662 if (strrchr(a->filename, '/')) |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1663 a_title = strrchr(a->filename, '/') + 1; |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1664 else |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1665 a_title = a->filename; |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1666 } |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1667 |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1668 if (b->title != NULL) |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1669 b_title = b->title; |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1670 else { |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1671 if (strrchr(a->filename, '/')) |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1672 b_title = strrchr(b->filename, '/') + 1; |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1673 else |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1674 b_title = b->filename; |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1675 } |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1676 |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1677 return strcasecmp(a_title, b_title); |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1678 } |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1679 |
740c08db08d9
[svn] via Christian Birchinger <joker -at- netswarm.net>:
nenolod
parents:
1415
diff
changeset
|
1680 static gint |
1251 | 1681 playlist_compare_title(PlaylistEntry * a, |
1682 PlaylistEntry * b) | |
0 | 1683 { |
1250 | 1684 const gchar *a_title = NULL, *b_title = NULL; |
0 | 1685 |
1686 g_return_val_if_fail(a != NULL, 0); | |
1687 g_return_val_if_fail(b != NULL, 0); | |
1688 | |
1250 | 1689 if (a->tuple != NULL && a->tuple->track_name != NULL) |
1690 a_title = a->tuple->track_name; | |
1691 if (b->tuple != NULL && b->tuple->track_name != NULL) | |
1692 b_title = b->tuple->track_name; | |
1693 | |
1251 | 1694 if (a_title != NULL && b_title != NULL) |
1250 | 1695 return strcasecmp(a_title, b_title); |
1696 | |
1697 if (a->title != NULL) | |
0 | 1698 a_title = a->title; |
1699 else { | |
1700 if (strrchr(a->filename, '/')) | |
1701 a_title = strrchr(a->filename, '/') + 1; | |
1702 else | |
1703 a_title = a->filename; | |
1704 } | |
1705 | |
1250 | 1706 if (b->title != NULL) |
0 | 1707 b_title = b->title; |
1708 else { | |
1709 if (strrchr(a->filename, '/')) | |
1710 b_title = strrchr(b->filename, '/') + 1; | |
1711 else | |
1712 b_title = b->filename; | |
1713 } | |
1714 | |
1715 return strcasecmp(a_title, b_title); | |
1716 } | |
1717 | |
1718 static gint | |
1251 | 1719 playlist_compare_artist(PlaylistEntry * a, |
1720 PlaylistEntry * b) | |
1721 { | |
1722 const gchar *a_artist = NULL, *b_artist = NULL; | |
1723 | |
1724 g_return_val_if_fail(a != NULL, 0); | |
1725 g_return_val_if_fail(b != NULL, 0); | |
1726 | |
1727 if (a->tuple != NULL) | |
1728 playlist_entry_get_info(a); | |
1729 | |
1730 if (b->tuple != NULL) | |
1731 playlist_entry_get_info(b); | |
1732 | |
1253
665dfbf5e9a1
[svn] - playlist_compare_artist(): more sanity checking.
nenolod
parents:
1251
diff
changeset
|
1733 if (a->tuple != NULL && a->tuple->performer != NULL) |
1251 | 1734 a_artist = a->tuple->performer; |
1253
665dfbf5e9a1
[svn] - playlist_compare_artist(): more sanity checking.
nenolod
parents:
1251
diff
changeset
|
1735 if (b->tuple != NULL && b->tuple->performer != NULL) |
1251 | 1736 b_artist = b->tuple->performer; |
1737 | |
1738 if (a_artist != NULL && b_artist != NULL) | |
1739 return strcasecmp(a_artist, b_artist); | |
1740 | |
1253
665dfbf5e9a1
[svn] - playlist_compare_artist(): more sanity checking.
nenolod
parents:
1251
diff
changeset
|
1741 return 0; |
1251 | 1742 } |
1743 | |
1744 static gint | |
1745 playlist_compare_filename(PlaylistEntry * a, | |
1746 PlaylistEntry * b) | |
0 | 1747 { |
1748 gchar *a_filename, *b_filename; | |
1749 | |
1750 g_return_val_if_fail(a != NULL, 0); | |
1751 g_return_val_if_fail(b != NULL, 0); | |
1752 | |
1753 if (strrchr(a->filename, '/')) | |
1754 a_filename = strrchr(a->filename, '/') + 1; | |
1755 else | |
1756 a_filename = a->filename; | |
1757 | |
1758 if (strrchr(b->filename, '/')) | |
1759 b_filename = strrchr(b->filename, '/') + 1; | |
1760 else | |
1761 b_filename = b->filename; | |
1762 | |
1763 | |
1764 return strcasecmp(a_filename, b_filename); | |
1765 } | |
1766 | |
1767 static gint | |
1768 path_compare(const gchar * a, const gchar * b) | |
1769 { | |
1770 gchar *posa, *posb; | |
1771 gint len, ret; | |
1772 | |
1773 posa = strrchr(a, '/'); | |
1774 posb = strrchr(b, '/'); | |
1775 | |
1776 /* | |
1777 * Sort directories before files | |
1778 */ | |
1779 if (posa && posb && (posa - a != posb - b)) { | |
1780 if (posa - a > posb - b) { | |
1781 len = posb - b; | |
1782 ret = -1; | |
1783 } | |
1784 else { | |
1785 len = posa - a; | |
1786 ret = 1; | |
1787 } | |
1788 if (!strncasecmp(a, b, len)) | |
1789 return ret; | |
1790 } | |
1791 return strcasecmp(a, b); | |
1792 } | |
1793 | |
1794 static gint | |
1251 | 1795 playlist_compare_path(PlaylistEntry * a, |
1796 PlaylistEntry * b) | |
0 | 1797 { |
1798 return path_compare(a->filename, b->filename); | |
1799 } | |
1800 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1801 |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1802 static time_t |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1803 playlist_get_mtime(const gchar *filename) |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1804 { |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1805 struct stat buf; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1806 |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1807 gint rv; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1808 |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1809 rv = stat(filename, &buf); |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1810 |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1811 if (rv == 0) { |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1812 return buf.st_mtime; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1813 } else { |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1814 return 0; //error |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1815 } |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1816 } |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1817 |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
1818 |
0 | 1819 static gint |
1251 | 1820 playlist_compare_date(PlaylistEntry * a, |
1821 PlaylistEntry * b) | |
0 | 1822 { |
1823 struct stat buf; | |
1824 time_t modtime; | |
1825 | |
1826 gint rv; | |
1827 | |
1828 | |
1829 rv = stat(a->filename, &buf); | |
1830 | |
1831 if (rv == 0) { | |
1832 modtime = buf.st_mtime; | |
1833 rv = stat(b->filename, &buf); | |
1834 | |
1835 if (stat(b->filename, &buf) == 0) { | |
1836 if (buf.st_mtime == modtime) | |
1837 return 0; | |
1838 else | |
1839 return (buf.st_mtime - modtime) > 0 ? -1 : 1; | |
1840 } | |
1841 else | |
1842 return -1; | |
1843 } | |
1844 else if (!lstat(b->filename, &buf)) | |
1845 return 1; | |
1846 else | |
1847 return playlist_compare_filename(a, b); | |
1848 } | |
1849 | |
1850 | |
1851 void | |
1852 playlist_sort(PlaylistSortType type) | |
1853 { | |
1854 playlist_remove_dead_files(); | |
1855 PLAYLIST_LOCK(); | |
1856 playlist = | |
1857 g_list_sort(playlist, | |
1858 (GCompareFunc) playlist_compare_func_table[type]); | |
1859 PLAYLIST_UNLOCK(); | |
1860 } | |
1861 | |
1862 static GList * | |
1863 playlist_sort_selected_generic(GList * list, GCompareFunc cmpfunc) | |
1864 { | |
1865 GList *list1, *list2; | |
1866 GList *tmp_list = NULL; | |
1867 GList *index_list = NULL; | |
1868 | |
1869 /* | |
1870 * We take all the selected entries out of the playlist, | |
1871 * sorts them, and then put them back in again. | |
1872 */ | |
1873 | |
1874 list1 = g_list_last(list); | |
1875 | |
1876 while (list1) { | |
1877 list2 = g_list_previous(list1); | |
1878 if (PLAYLIST_ENTRY(list1->data)->selected) { | |
1879 gpointer idx; | |
1880 idx = GINT_TO_POINTER(g_list_position(list, list1)); | |
1881 index_list = g_list_prepend(index_list, idx); | |
1882 list = g_list_remove_link(list, list1); | |
1883 tmp_list = g_list_concat(list1, tmp_list); | |
1884 } | |
1885 list1 = list2; | |
1886 } | |
1887 | |
1888 tmp_list = g_list_sort(tmp_list, cmpfunc); | |
1889 list1 = tmp_list; | |
1890 list2 = index_list; | |
1891 | |
1892 while (list2) { | |
1893 if (!list1) { | |
1894 g_critical(G_STRLOC ": Error during list sorting. " | |
1895 "Possibly dropped some playlist-entries."); | |
1896 break; | |
1897 } | |
1898 | |
1899 list = g_list_insert(list, list1->data, GPOINTER_TO_INT(list2->data)); | |
1900 | |
1901 list2 = g_list_next(list2); | |
1902 list1 = g_list_next(list1); | |
1903 } | |
1904 | |
1905 g_list_free(index_list); | |
1906 g_list_free(tmp_list); | |
1907 | |
1908 return list; | |
1909 } | |
1910 | |
1911 void | |
1912 playlist_sort_selected(PlaylistSortType type) | |
1913 { | |
1914 PLAYLIST_LOCK(); | |
1915 playlist = playlist_sort_selected_generic(playlist, (GCompareFunc) | |
1916 playlist_compare_func_table | |
1917 [type]); | |
1918 PLAYLIST_UNLOCK(); | |
1919 } | |
1920 | |
1921 void | |
1922 playlist_reverse(void) | |
1923 { | |
1924 PLAYLIST_LOCK(); | |
1925 playlist = g_list_reverse(playlist); | |
1926 PLAYLIST_UNLOCK(); | |
1927 } | |
1928 | |
1929 static GList * | |
1930 playlist_shuffle_list(GList * list) | |
1931 { | |
1932 /* | |
1933 * Note that this doesn't make a copy of the original list. | |
1934 * The pointer to the original list is not valid after this | |
1935 * fuction is run. | |
1936 */ | |
1937 gint len = g_list_length(list); | |
1938 gint i, j; | |
1939 GList *node, **ptrs; | |
1940 | |
1941 REQUIRE_STATIC_LOCK(playlist); | |
1942 | |
1943 if (!len) | |
1944 return NULL; | |
1945 | |
1946 ptrs = g_new(GList *, len); | |
1947 | |
1948 for (node = list, i = 0; i < len; node = g_list_next(node), i++) | |
1949 ptrs[i] = node; | |
1950 | |
1951 j = g_random_int_range(0, len); | |
1952 list = ptrs[j]; | |
1953 ptrs[j]->next = NULL; | |
1954 ptrs[j] = ptrs[0]; | |
1955 | |
1956 for (i = 1; i < len; i++) { | |
1957 j = g_random_int_range(0, len - i); | |
1958 list->prev = ptrs[i + j]; | |
1959 ptrs[i + j]->next = list; | |
1960 list = ptrs[i + j]; | |
1961 ptrs[i + j] = ptrs[i]; | |
1962 } | |
1963 list->prev = NULL; | |
1964 | |
1965 g_free(ptrs); | |
1966 | |
1967 return list; | |
1968 } | |
1969 | |
1970 void | |
1971 playlist_random(void) | |
1972 { | |
1973 PLAYLIST_LOCK(); | |
1974 playlist = playlist_shuffle_list(playlist); | |
1975 PLAYLIST_UNLOCK(); | |
1976 } | |
1977 | |
1978 GList * | |
1979 playlist_get_selected(void) | |
1980 { | |
1981 GList *node, *list = NULL; | |
1982 gint i = 0; | |
1983 | |
1984 PLAYLIST_LOCK(); | |
1985 for (node = playlist_get(); node; node = g_list_next(node), i++) { | |
1986 PlaylistEntry *entry = node->data; | |
1987 if (entry->selected) | |
1988 list = g_list_prepend(list, GINT_TO_POINTER(i)); | |
1989 } | |
1990 PLAYLIST_UNLOCK(); | |
1991 return g_list_reverse(list); | |
1992 } | |
1993 | |
1994 void | |
1995 playlist_clear_selected(void) | |
1996 { | |
1997 GList *node = NULL; | |
1998 gint i = 0; | |
1999 | |
2000 PLAYLIST_LOCK(); | |
2001 for (node = playlist_get(); node; node = g_list_next(node), i++) { | |
2002 PLAYLIST_ENTRY(node->data)->selected = FALSE; | |
2003 } | |
2004 PLAYLIST_UNLOCK(); | |
2005 playlist_recalc_total_time(); | |
2006 } | |
2007 | |
2008 gint | |
2009 playlist_get_num_selected(void) | |
2010 { | |
2011 GList *node; | |
2012 gint num = 0; | |
2013 | |
2014 PLAYLIST_LOCK(); | |
2015 for (node = playlist_get(); node; node = g_list_next(node)) { | |
2016 PlaylistEntry *entry = node->data; | |
2017 if (entry->selected) | |
2018 num++; | |
2019 } | |
2020 PLAYLIST_UNLOCK(); | |
2021 return num; | |
2022 } | |
2023 | |
2024 | |
2025 static void | |
2026 playlist_generate_shuffle_list(void) | |
2027 { | |
2028 PLAYLIST_LOCK(); | |
2029 playlist_generate_shuffle_list_nolock(); | |
2030 PLAYLIST_UNLOCK(); | |
2031 } | |
2032 | |
2033 static void | |
2034 playlist_generate_shuffle_list_nolock(void) | |
2035 { | |
2036 GList *node; | |
2037 gint numsongs; | |
2038 | |
2039 REQUIRE_STATIC_LOCK(playlist); | |
2040 | |
2041 if (shuffle_list) { | |
2042 g_list_free(shuffle_list); | |
2043 shuffle_list = NULL; | |
2044 } | |
2045 | |
2046 if (!cfg.shuffle || !playlist) | |
2047 return; | |
2048 | |
2049 shuffle_list = playlist_shuffle_list(g_list_copy(playlist)); | |
2050 numsongs = g_list_length(shuffle_list); | |
2051 | |
2052 if (playlist_position) { | |
2053 gint i = g_list_index(shuffle_list, playlist_position); | |
2054 node = g_list_nth(shuffle_list, i); | |
2055 shuffle_list = g_list_remove_link(shuffle_list, node); | |
2056 shuffle_list = g_list_prepend(shuffle_list, node->data); | |
2057 } | |
2058 } | |
2059 | |
2060 void | |
2061 playlist_fileinfo(guint pos) | |
2062 { | |
2063 gchar *path = NULL; | |
2064 GList *node; | |
1269 | 2065 PlaylistEntry *entry = NULL; |
2066 TitleInput *tuple = NULL; | |
0 | 2067 |
2068 PLAYLIST_LOCK(); | |
1269 | 2069 |
2070 if ((node = g_list_nth(playlist_get(), pos))) | |
2071 { | |
2072 entry = node->data; | |
2073 tuple = entry->tuple; | |
1516
3483fb26b9fb
[svn] - when audacious is started and track detail on current song are requested, try to check if a decoder exists before falling back to the tuple display dialog
giacomo
parents:
1459
diff
changeset
|
2074 path = g_strdup(entry->filename); |
0 | 2075 } |
1269 | 2076 |
0 | 2077 PLAYLIST_UNLOCK(); |
1277
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
2078 |
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
2079 /* No tuple? Try to set this entry up properly. --nenolod */ |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2080 // if (entry->tuple == NULL) |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2081 if (!entry->tuple || (entry->tuple->mtime != playlist_get_mtime(entry->filename))) |
1277
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
2082 { |
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
2083 playlist_entry_get_info(entry); |
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
2084 tuple = entry->tuple; |
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
2085 } |
8c8d4841efae
[svn] - if entry->tuple == NULL, then probe the file for a decoder and build the appropriate tuple for that entry
nenolod
parents:
1270
diff
changeset
|
2086 |
1269 | 2087 if (tuple != NULL) |
2088 { | |
2089 if (entry->decoder != NULL && entry->decoder->file_info_box == NULL) | |
2090 fileinfo_show_for_tuple(tuple); | |
1270 | 2091 else if (entry->decoder != NULL && entry->decoder->file_info_box != NULL) |
2092 entry->decoder->file_info_box(path); | |
1269 | 2093 else |
2094 fileinfo_show_for_path(path); | |
2095 g_free(path); | |
2096 } | |
2097 else if (path != NULL) | |
2098 { | |
1270 | 2099 if (entry != NULL && entry->decoder != NULL && entry->decoder->file_info_box != NULL) |
2100 entry->decoder->file_info_box(path); | |
2101 else | |
2102 fileinfo_show_for_path(path); | |
0 | 2103 g_free(path); |
2104 } | |
2105 } | |
2106 | |
2107 void | |
2108 playlist_fileinfo_current(void) | |
2109 { | |
2110 gchar *path = NULL; | |
1269 | 2111 TitleInput *tuple = NULL; |
0 | 2112 |
2113 PLAYLIST_LOCK(); | |
1269 | 2114 |
0 | 2115 if (playlist_get() && playlist_position) |
1269 | 2116 { |
0 | 2117 path = g_strdup(playlist_position->filename); |
1516
3483fb26b9fb
[svn] - when audacious is started and track detail on current song are requested, try to check if a decoder exists before falling back to the tuple display dialog
giacomo
parents:
1459
diff
changeset
|
2118 if ( playlist_position->tuple == NULL ) |
3483fb26b9fb
[svn] - when audacious is started and track detail on current song are requested, try to check if a decoder exists before falling back to the tuple display dialog
giacomo
parents:
1459
diff
changeset
|
2119 playlist_entry_get_info(playlist_position); |
3483fb26b9fb
[svn] - when audacious is started and track detail on current song are requested, try to check if a decoder exists before falling back to the tuple display dialog
giacomo
parents:
1459
diff
changeset
|
2120 tuple = playlist_position->tuple; |
1269 | 2121 } |
2122 | |
0 | 2123 PLAYLIST_UNLOCK(); |
2124 | |
1269 | 2125 if (tuple != NULL) |
2126 { | |
2127 if (playlist_position->decoder != NULL && playlist_position->decoder->file_info_box == NULL) | |
2128 fileinfo_show_for_tuple(tuple); | |
1270 | 2129 else if (playlist_position->decoder != NULL && playlist_position->decoder->file_info_box != NULL) |
2130 playlist_position->decoder->file_info_box(path); | |
1269 | 2131 else |
2132 fileinfo_show_for_path(path); | |
2133 g_free(path); | |
2134 } | |
2135 else if (path != NULL) | |
2136 { | |
1270 | 2137 if (playlist_position != NULL && playlist_position->decoder != NULL && playlist_position->decoder->file_info_box != NULL) |
2138 playlist_position->decoder->file_info_box(path); | |
2139 else | |
2140 fileinfo_show_for_path(path); | |
0 | 2141 g_free(path); |
2142 } | |
2143 } | |
2144 | |
2145 | |
2146 static gboolean | |
2147 playlist_get_info_is_going(void) | |
2148 { | |
2149 gboolean result; | |
2150 | |
2151 G_LOCK(playlist_get_info_going); | |
2152 result = playlist_get_info_going; | |
2153 G_UNLOCK(playlist_get_info_going); | |
2154 | |
2155 return result; | |
2156 } | |
2157 | |
2158 static gpointer | |
2159 playlist_get_info_func(gpointer arg) | |
2160 { | |
2161 GList *node; | |
2162 gboolean update_playlistwin = FALSE; | |
2163 gboolean update_mainwin = FALSE; | |
2164 | |
2165 while (playlist_get_info_is_going()) { | |
2166 PlaylistEntry *entry; | |
2167 | |
2168 if (cfg.use_pl_metadata && | |
2169 cfg.get_info_on_load && | |
2170 playlist_get_info_scan_active) { | |
2171 | |
2172 PLAYLIST_LOCK(); | |
2173 for (node = playlist_get(); node; node = g_list_next(node)) { | |
2174 entry = node->data; | |
2175 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2176 if(entry->tuple) { |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2177 // printf("tuple mtime = %ld file mtime = %ld\n", entry->tuple->mtime, playlist_get_mtime(entry->filename)); |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2178 if(entry->tuple->mtime == playlist_get_mtime(entry->filename)) |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2179 continue; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2180 else |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2181 entry->tuple->mtime = 0; /* invalidate mtime */ |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2182 } |
0 | 2183 |
2184 if (!playlist_entry_get_info(entry)) { | |
2185 if (g_list_index(playlist_get(), entry) == -1) | |
2186 /* Entry disappeared while we looked it up. | |
2187 Restart. */ | |
2188 node = playlist_get(); | |
2189 } | |
2190 else if (entry->title || entry->length != -1) { | |
2191 update_playlistwin = TRUE; | |
2192 if (entry == playlist_position) | |
2193 update_mainwin = TRUE; | |
2194 break; | |
2195 } | |
2196 } | |
2197 PLAYLIST_UNLOCK(); | |
2198 | |
2199 if (!node) | |
2200 playlist_get_info_scan_active = FALSE; | |
2201 } | |
2202 else if (!cfg.get_info_on_load && | |
2203 cfg.get_info_on_demand && | |
2204 cfg.playlist_visible && | |
2205 !cfg.playlist_shaded && | |
2206 cfg.use_pl_metadata) { | |
2207 | |
2208 gboolean found = FALSE; | |
2209 | |
2210 PLAYLIST_LOCK(); | |
2211 | |
2212 if (!playlist_get()) { | |
2213 PLAYLIST_UNLOCK(); | |
2214 g_usleep(1000000); | |
2215 continue; | |
2216 } | |
2217 | |
2218 for (node = | |
2219 g_list_nth(playlist_get(), playlistwin_get_toprow()); | |
2220 node | |
2221 && | |
2222 playlistwin_item_visible(g_list_position | |
2223 (playlist_get(), node)); | |
2224 node = g_list_next(node)) { | |
2225 entry = node->data; | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2226 // if (entry->title || entry->length != -1) |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2227 if (entry->tuple && (entry->tuple->mtime == playlist_get_mtime(entry->filename))) |
0 | 2228 continue; |
2229 | |
2230 if (!playlist_entry_get_info(entry)) { | |
2231 if (g_list_index(playlist_get(), entry) == -1) | |
2232 /* Entry disapeared while we | |
2233 looked it up. Restart. */ | |
2234 node = | |
2235 g_list_nth(playlist_get(), | |
2236 playlistwin_get_toprow()); | |
2237 } | |
2238 else if (entry->title || entry->length != -1) { | |
2239 update_playlistwin = TRUE; | |
2240 if (entry == playlist_position) | |
2241 update_mainwin = TRUE; | |
2242 found = TRUE; | |
2243 break; | |
2244 } | |
2245 } | |
2246 | |
2247 PLAYLIST_UNLOCK(); | |
2248 | |
2249 if (!found) { | |
2250 g_usleep(500000); | |
2251 continue; | |
2252 } | |
2253 } | |
2254 else | |
2255 g_usleep(500000); | |
2256 | |
2257 if (update_playlistwin) { | |
2258 playlistwin_update_list(); | |
2259 update_playlistwin = FALSE; | |
2260 } | |
2261 | |
2262 if (update_mainwin) { | |
2263 mainwin_set_info_text(); | |
2264 update_mainwin = FALSE; | |
2265 } | |
2266 } | |
2267 | |
2268 g_thread_exit(NULL); | |
2269 return NULL; | |
2270 } | |
2271 | |
2272 void | |
2273 playlist_start_get_info_thread(void) | |
2274 { | |
2275 playlist_get_info_going = TRUE; | |
2276 playlist_get_info_thread = g_thread_create(playlist_get_info_func, | |
2277 NULL, TRUE, NULL); | |
2278 } | |
2279 | |
2280 void | |
2281 playlist_stop_get_info_thread(void) | |
2282 { | |
2283 G_LOCK(playlist_get_info_going); | |
2284 playlist_get_info_going = FALSE; | |
2285 G_UNLOCK(playlist_get_info_going); | |
2286 g_thread_join(playlist_get_info_thread); | |
2287 } | |
2288 | |
2289 void | |
2290 playlist_start_get_info_scan(void) | |
2291 { | |
2292 playlist_get_info_scan_active = TRUE; | |
2293 } | |
2294 | |
2295 void | |
2296 playlist_remove_dead_files(void) | |
2297 { | |
2298 GList *node, *next_node; | |
2299 | |
2300 PLAYLIST_LOCK(); | |
2301 | |
2302 for (node = playlist; node; node = next_node) { | |
2303 PlaylistEntry *entry = PLAYLIST_ENTRY(node->data); | |
2304 next_node = g_list_next(node); | |
2305 | |
2306 if (!entry || !entry->filename) { | |
2307 g_message(G_STRLOC ": Playlist entry is invalid!"); | |
2308 continue; | |
2309 } | |
2310 | |
2311 /* FIXME: What about 'file:///'? */ | |
2312 /* Don't kill URLs */ | |
2313 if (strstr(entry->filename, "://")) | |
2314 continue; | |
2315 | |
2316 /* FIXME: Should test for readability */ | |
2317 if (vfs_file_test(entry->filename, G_FILE_TEST_EXISTS)) | |
2318 continue; | |
2319 | |
2320 if (entry == playlist_position) { | |
2321 /* Don't remove the currently playing song */ | |
2322 if (bmp_playback_get_playing()) | |
2323 continue; | |
2324 | |
2325 if (next_node) | |
2326 playlist_position = PLAYLIST_ENTRY(next_node->data); | |
2327 else | |
2328 playlist_position = NULL; | |
2329 } | |
2330 | |
2331 playlist_entry_free(entry); | |
2332 playlist = g_list_delete_link(playlist, node); | |
2333 } | |
2334 | |
2335 PLAYLIST_UNLOCK(); | |
2336 | |
2337 playlist_generate_shuffle_list(); | |
2338 playlistwin_update_list(); | |
2339 playlist_recalc_total_time(); | |
2340 } | |
2341 | |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2342 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2343 static gint |
1251 | 2344 playlist_dupscmp_title(PlaylistEntry * a, |
2345 PlaylistEntry * b) | |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2346 { |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2347 const gchar *a_title, *b_title; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2348 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2349 g_return_val_if_fail(a != NULL, 0); |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2350 g_return_val_if_fail(b != NULL, 0); |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2351 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2352 if (a->title) |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2353 a_title = a->title; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2354 else { |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2355 if (strrchr(a->filename, '/')) |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2356 a_title = strrchr(a->filename, '/') + 1; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2357 else |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2358 a_title = a->filename; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2359 } |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2360 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2361 if (b->title) |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2362 b_title = b->title; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2363 else { |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2364 if (strrchr(a->filename, '/')) |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2365 b_title = strrchr(b->filename, '/') + 1; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2366 else |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2367 b_title = b->filename; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2368 } |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2369 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2370 return strcmp(a_title, b_title); |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2371 } |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2372 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2373 static gint |
1251 | 2374 playlist_dupscmp_filename(PlaylistEntry * a, |
2375 PlaylistEntry * b ) | |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2376 { |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2377 gchar *a_filename, *b_filename; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2378 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2379 g_return_val_if_fail(a != NULL, 0); |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2380 g_return_val_if_fail(b != NULL, 0); |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2381 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2382 if (strrchr(a->filename, '/')) |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2383 a_filename = strrchr(a->filename, '/') + 1; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2384 else |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2385 a_filename = a->filename; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2386 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2387 if (strrchr(b->filename, '/')) |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2388 b_filename = strrchr(b->filename, '/') + 1; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2389 else |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2390 b_filename = b->filename; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2391 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2392 return strcmp(a_filename, b_filename); |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2393 } |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2394 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2395 static gint |
1251 | 2396 playlist_dupscmp_path(PlaylistEntry * a, |
2397 PlaylistEntry * b) | |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2398 { |
853 | 2399 /* simply compare the entire filename string */ |
2400 return strcmp(a->filename, b->filename); | |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2401 } |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2402 |
840
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2403 void |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2404 playlist_remove_duplicates( PlaylistDupsType type ) |
840
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2405 { |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2406 GList *node, *next_node; |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2407 GList *node_cmp, *next_node_cmp; |
1251 | 2408 gint (*dups_compare_func)(PlaylistEntry * , PlaylistEntry *); |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2409 |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2410 switch ( type ) |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2411 { |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2412 case PLAYLIST_DUPS_TITLE: |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2413 dups_compare_func = playlist_dupscmp_title; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2414 break; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2415 case PLAYLIST_DUPS_PATH: |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2416 dups_compare_func = playlist_dupscmp_path; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2417 break; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2418 case PLAYLIST_DUPS_FILENAME: |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2419 default: |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2420 dups_compare_func = playlist_dupscmp_filename; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2421 break; |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2422 } |
840
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2423 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2424 PLAYLIST_LOCK(); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2425 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2426 for (node = playlist; node; node = next_node) { |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2427 PlaylistEntry *entry = PLAYLIST_ENTRY(node->data); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2428 next_node = g_list_next(node); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2429 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2430 if (!entry || !entry->filename) { |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2431 g_message(G_STRLOC ": Playlist entry is invalid!"); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2432 continue; |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2433 } |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2434 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2435 for (node_cmp = next_node; node_cmp; node_cmp = next_node_cmp) { |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2436 PlaylistEntry *entry_cmp = PLAYLIST_ENTRY(node_cmp->data); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2437 next_node_cmp = g_list_next(node_cmp); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2438 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2439 if (!entry_cmp || !entry_cmp->filename) { |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2440 g_message(G_STRLOC ": Playlist entry is invalid!"); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2441 continue; |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2442 } |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2443 |
852
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2444 /* compare using the chosen dups_compare_func */ |
bcff46a2558d
[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
giacomo
parents:
840
diff
changeset
|
2445 if ( !dups_compare_func( entry , entry_cmp ) ) { |
840
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2446 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2447 if (entry_cmp == playlist_position) { |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2448 /* Don't remove the currently playing song */ |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2449 if (bmp_playback_get_playing()) |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2450 continue; |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2451 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2452 if (next_node_cmp) |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2453 playlist_position = PLAYLIST_ENTRY(next_node_cmp->data); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2454 else |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2455 playlist_position = NULL; |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2456 } |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2457 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2458 /* check if this was the next item of the external |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2459 loop; if true, replace it with the next of the next*/ |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2460 if ( node_cmp == next_node ) |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2461 next_node = g_list_next(next_node); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2462 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2463 playlist_entry_free(entry_cmp); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2464 playlist = g_list_delete_link(playlist, node_cmp); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2465 } |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2466 } |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2467 } |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2468 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2469 PLAYLIST_UNLOCK(); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2470 |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2471 playlistwin_update_list(); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2472 playlist_recalc_total_time(); |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2473 } |
ffc5ab7b4b2c
[svn] added a 'remove duplicates' option to the playlist removal menu
giacomo
parents:
633
diff
changeset
|
2474 |
0 | 2475 static gulong pl_total_time = 0, pl_selection_time = 0; |
2476 static gboolean pl_total_more = FALSE, pl_selection_more = FALSE; | |
2477 | |
2478 void | |
2479 playlist_get_total_time(gulong * total_time, | |
2480 gulong * selection_time, | |
2481 gboolean * total_more, | |
2482 gboolean * selection_more) | |
2483 { | |
2484 PLAYLIST_LOCK(); | |
2485 *total_time = pl_total_time; | |
2486 *selection_time = pl_selection_time; | |
2487 *total_more = pl_total_more; | |
2488 *selection_more = pl_selection_more; | |
2489 PLAYLIST_UNLOCK(); | |
2490 } | |
2491 | |
2492 | |
2493 static void | |
2494 playlist_recalc_total_time_nolock(void) | |
2495 { | |
2496 GList *list; | |
2497 PlaylistEntry *entry; | |
2498 | |
2499 REQUIRE_STATIC_LOCK(playlist); | |
2500 | |
2501 pl_total_time = 0; | |
2502 pl_selection_time = 0; | |
2503 pl_total_more = FALSE; | |
2504 pl_selection_more = FALSE; | |
2505 | |
2506 for (list = playlist_get(); list; list = g_list_next(list)) { | |
2507 entry = list->data; | |
2508 | |
2509 if (entry->length != -1) | |
2510 pl_total_time += entry->length / 1000; | |
2511 else | |
2512 pl_total_more = TRUE; | |
2513 | |
2514 if (entry->selected) { | |
2515 if (entry->length != -1) | |
2516 pl_selection_time += entry->length / 1000; | |
2517 else | |
2518 pl_selection_more = TRUE; | |
2519 } | |
2520 } | |
2521 } | |
2522 | |
2523 static void | |
2524 playlist_recalc_total_time(void) | |
2525 { | |
2526 PLAYLIST_LOCK(); | |
2527 playlist_recalc_total_time_nolock(); | |
2528 PLAYLIST_UNLOCK(); | |
2529 } | |
2530 | |
2531 | |
2532 void | |
2533 playlist_select_all(gboolean set) | |
2534 { | |
2535 GList *list; | |
2536 | |
2537 PLAYLIST_LOCK(); | |
2538 | |
2539 for (list = playlist_get(); list; list = g_list_next(list)) { | |
2540 PlaylistEntry *entry = list->data; | |
2541 entry->selected = set; | |
2542 } | |
2543 | |
2544 PLAYLIST_UNLOCK(); | |
2545 playlist_recalc_total_time(); | |
2546 } | |
2547 | |
2548 void | |
2549 playlist_select_invert_all(void) | |
2550 { | |
2551 GList *list; | |
2552 | |
2553 PLAYLIST_LOCK(); | |
2554 | |
2555 for (list = playlist_get(); list; list = g_list_next(list)) { | |
2556 PlaylistEntry *entry = list->data; | |
2557 entry->selected = !entry->selected; | |
2558 } | |
2559 | |
2560 PLAYLIST_UNLOCK(); | |
2561 playlist_recalc_total_time(); | |
2562 } | |
2563 | |
2564 gboolean | |
2565 playlist_select_invert(guint pos) | |
2566 { | |
2567 GList *list; | |
2568 gboolean invert_ok = FALSE; | |
2569 | |
2570 PLAYLIST_LOCK(); | |
2571 | |
2572 if ((list = g_list_nth(playlist_get(), pos))) { | |
2573 PlaylistEntry *entry = list->data; | |
2574 entry->selected = !entry->selected; | |
2575 invert_ok = TRUE; | |
2576 } | |
2577 | |
2578 PLAYLIST_UNLOCK(); | |
2579 playlist_recalc_total_time(); | |
2580 | |
2581 return invert_ok; | |
2582 } | |
2583 | |
2584 | |
2585 void | |
2586 playlist_select_range(gint min_pos, gint max_pos, gboolean select) | |
2587 { | |
2588 GList *list; | |
2589 gint i; | |
2590 | |
2591 if (min_pos > max_pos) | |
2592 SWAP(min_pos, max_pos); | |
2593 | |
2594 PLAYLIST_LOCK(); | |
2595 | |
2596 list = g_list_nth(playlist_get(), min_pos); | |
2597 for (i = min_pos; i <= max_pos && list; i++) { | |
2598 PlaylistEntry *entry = list->data; | |
2599 entry->selected = select; | |
2600 list = g_list_next(list); | |
2601 } | |
2602 | |
2603 PLAYLIST_UNLOCK(); | |
2604 | |
2605 playlist_recalc_total_time(); | |
2606 } | |
2607 | |
2608 gboolean | |
2609 playlist_read_info_selection(void) | |
2610 { | |
2611 GList *node; | |
2612 gboolean retval = FALSE; | |
2613 | |
2614 PLAYLIST_LOCK(); | |
2615 | |
2616 for (node = playlist_get(); node; node = g_list_next(node)) { | |
2617 PlaylistEntry *entry = node->data; | |
2618 if (!entry->selected) | |
2619 continue; | |
2620 | |
2621 retval = TRUE; | |
2622 | |
2623 str_replace_in(&entry->title, NULL); | |
2624 entry->length = -1; | |
2625 | |
1588
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2626 /* invalidate mtime to reread */ |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2627 entry->tuple->mtime = 0; |
15d92c51bde6
[svn] - modified time (mtime) has been introduced into tuple
yaz
parents:
1587
diff
changeset
|
2628 |
0 | 2629 if (!playlist_entry_get_info(entry)) { |
2630 if (g_list_index(playlist_get(), entry) == -1) | |
2631 /* Entry disappeared while we looked it up. Restart. */ | |
2632 node = playlist_get(); | |
2633 } | |
2634 } | |
2635 | |
2636 PLAYLIST_UNLOCK(); | |
2637 | |
2638 playlistwin_update_list(); | |
2639 playlist_recalc_total_time(); | |
2640 | |
2641 return retval; | |
2642 } | |
2643 | |
2644 void | |
2645 playlist_read_info(guint pos) | |
2646 { | |
2647 GList *node; | |
2648 | |
2649 PLAYLIST_LOCK(); | |
2650 | |
2651 if ((node = g_list_nth(playlist_get(), pos))) { | |
2652 PlaylistEntry *entry = node->data; | |
2653 str_replace_in(&entry->title, NULL); | |
2654 entry->length = -1; | |
2655 playlist_entry_get_info(entry); | |
2656 } | |
2657 | |
2658 PLAYLIST_UNLOCK(); | |
2659 | |
2660 playlistwin_update_list(); | |
2661 playlist_recalc_total_time(); | |
2662 } | |
2663 | |
2664 void | |
2665 playlist_set_shuffle(gboolean shuffle) | |
2666 { | |
2667 PLAYLIST_LOCK(); | |
2668 | |
2669 cfg.shuffle = shuffle; | |
2670 playlist_generate_shuffle_list_nolock(); | |
2671 | |
2672 PLAYLIST_UNLOCK(); | |
2673 } | |
2674 | |
2675 void | |
2676 playlist_new(void) | |
2677 { | |
2678 playlist_set_current_name(NULL); | |
2679 playlist_clear(); | |
2680 mainwin_clear_song_info(); | |
2681 mainwin_set_info_text(); | |
2682 } | |
2683 | |
2684 | |
2685 const gchar * | |
2686 playlist_get_filename_to_play(void) | |
2687 { | |
2688 const gchar *filename = NULL; | |
2689 | |
2690 PLAYLIST_LOCK(); | |
2691 | |
2692 if (playlist) { | |
2693 if (!playlist_position) { | |
2694 if (cfg.shuffle) | |
2695 playlist_position = shuffle_list->data; | |
2696 else | |
2697 playlist_position = playlist->data; | |
2698 } | |
2699 | |
2700 filename = playlist_position->filename; | |
2701 } | |
2702 | |
2703 PLAYLIST_UNLOCK(); | |
2704 | |
2705 return filename; | |
2706 } | |
356
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2707 |
398
f908bcd87c3d
[svn] Generate cache content on demand if it was not previously there.
nenolod
parents:
397
diff
changeset
|
2708 PlaylistEntry * |
356
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2709 playlist_get_entry_to_play(void) |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2710 { |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2711 PLAYLIST_LOCK(); |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2712 |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2713 if (playlist) { |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2714 if (!playlist_position) { |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2715 if (cfg.shuffle) |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2716 playlist_position = shuffle_list->data; |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2717 else |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2718 playlist_position = playlist->data; |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2719 } |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2720 } |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2721 |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2722 PLAYLIST_UNLOCK(); |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2723 |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2724 return playlist_position; |
99928e1275a1
[svn] This commit reduces the amount of times we probe a source down to ONE
nenolod
parents:
355
diff
changeset
|
2725 } |