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