2 * Copyright 2006 Timo Hirvonen
7 #include "track_info.h"
8 #include "search_mode.h"
17 static int xstrcasecmp(const char *a
, const char *b
)
23 } else if (b
== NULL
) {
26 return u_strcasecmp(a
, b
);
29 void simple_track_init(struct simple_track
*track
, struct track_info
*ti
)
33 track
->disc
= comments_get_int(ti
->comments
, "discnumber");
34 track
->num
= comments_get_int(ti
->comments
, "tracknumber");
37 struct simple_track
*simple_track_new(struct track_info
*ti
)
39 struct simple_track
*t
= xnew(struct simple_track
, 1);
42 simple_track_init(t
, ti
);
46 GENERIC_ITER_PREV(simple_track_get_prev
, struct simple_track
, node
)
47 GENERIC_ITER_NEXT(simple_track_get_next
, struct simple_track
, node
)
49 int simple_track_search_get_current(void *data
, struct iter
*iter
)
51 return window_get_sel(data
, iter
);
54 int simple_track_search_matches(void *data
, struct iter
*iter
, const char *text
)
56 unsigned int flags
= TI_MATCH_TITLE
;
57 struct simple_track
*track
= iter_to_simple_track(iter
);
59 if (!search_restricted
)
60 flags
|= TI_MATCH_ARTIST
| TI_MATCH_ALBUM
;
62 if (!track_info_matches(track
->info
, text
, flags
))
65 window_set_sel(data
, iter
);
69 struct shuffle_track
*shuffle_list_get_next(struct list_head
*head
, struct shuffle_track
*cur
,
70 int (*filter
)(const struct simple_track
*))
72 struct list_head
*item
;
75 return to_shuffle_track(head
->next
);
77 item
= cur
->node
.next
;
79 while (item
!= head
) {
80 struct shuffle_track
*track
= to_shuffle_track(item
);
82 if (filter((struct simple_track
*)track
))
95 struct shuffle_track
*shuffle_list_get_prev(struct list_head
*head
, struct shuffle_track
*cur
,
96 int (*filter
)(const struct simple_track
*))
98 struct list_head
*item
;
101 return to_shuffle_track(head
->next
);
103 item
= cur
->node
.prev
;
105 while (item
!= head
) {
106 struct shuffle_track
*track
= to_shuffle_track(item
);
108 if (filter((struct simple_track
*)track
))
121 struct simple_track
*simple_list_get_next(struct list_head
*head
, struct simple_track
*cur
,
122 int (*filter
)(const struct simple_track
*))
124 struct list_head
*item
;
127 return to_simple_track(head
->next
);
129 item
= cur
->node
.next
;
131 while (item
!= head
) {
132 struct simple_track
*track
= to_simple_track(item
);
144 struct simple_track
*simple_list_get_prev(struct list_head
*head
, struct simple_track
*cur
,
145 int (*filter
)(const struct simple_track
*))
147 struct list_head
*item
;
150 return to_simple_track(head
->next
);
152 item
= cur
->node
.prev
;
154 while (item
!= head
) {
155 struct simple_track
*track
= to_simple_track(item
);
167 int simple_track_cmp(const struct list_head
*a_head
, const struct list_head
*b_head
, const char * const *keys
)
169 const struct simple_track
*a
= to_simple_track(a_head
);
170 const struct simple_track
*b
= to_simple_track(b_head
);
173 for (i
= 0; keys
[i
]; i
++) {
174 const char *key
= keys
[i
];
176 const struct track_info
*ai
, *bi
;
178 /* numeric compare for tracknumber and discnumber */
179 if (strcmp(key
, "tracknumber") == 0) {
180 res
= a
->num
- b
->num
;
185 if (strcmp(key
, "discnumber") == 0) {
186 res
= a
->disc
- b
->disc
;
193 if (strcmp(key
, "filename") == 0) {
194 /* NOTE: filenames are not necessarily UTF-8 */
195 res
= strcasecmp(ai
->filename
, bi
->filename
);
200 av
= comments_get_val(ai
->comments
, key
);
201 bv
= comments_get_val(bi
->comments
, key
);
202 res
= xstrcasecmp(av
, bv
);
209 void sorted_list_add_track(struct list_head
*head
, struct simple_track
*track
, const char * const *keys
)
211 struct list_head
*item
;
213 /* It is _much_ faster to iterate in reverse order because playlist
214 * file is usually sorted.
217 while (item
!= head
) {
218 if (simple_track_cmp(&track
->node
, item
, keys
) >= 0)
223 list_add(&track
->node
, item
);
226 void shuffle_list_add_track(struct list_head
*head
, struct list_head
*node
, int nr
)
228 struct list_head
*item
;
231 pos
= rand() % (nr
+ 1);
239 list_add(node
, item
);
246 /* add before item */
247 list_add_tail(node
, item
);
251 void reshuffle(struct list_head
*head
)
253 struct list_head
*item
, *last
;
256 if (list_empty(head
))
264 struct list_head
*next
= item
->next
;
266 shuffle_list_add_track(head
, item
, i
++);
273 int simple_list_for_each_marked(struct list_head
*head
,
274 int (*cb
)(void *data
, struct track_info
*ti
), void *data
, int reverse
)
276 struct simple_track
*t
;
280 list_for_each_entry_reverse(t
, head
, node
) {
282 rc
= cb(data
, t
->info
);
288 list_for_each_entry(t
, head
, node
) {
290 rc
= cb(data
, t
->info
);