flac: Saner EOF handling
[cmus.git] / track.c
blobeb181b62dc027109548cd47667161b809b0d589c
1 /*
2 * Copyright 2006 Timo Hirvonen
3 */
5 #include "track.h"
6 #include "iter.h"
7 #include "track_info.h"
8 #include "search_mode.h"
9 #include "window.h"
10 #include "options.h"
11 #include "comment.h"
12 #include "uchar.h"
13 #include "xmalloc.h"
15 #include <string.h>
17 void simple_track_init(struct simple_track *track, struct track_info *ti)
19 track->info = ti;
20 track->marked = 0;
23 struct simple_track *simple_track_new(struct track_info *ti)
25 struct simple_track *t = xnew(struct simple_track, 1);
27 track_info_ref(ti);
28 simple_track_init(t, ti);
29 return t;
32 GENERIC_ITER_PREV(simple_track_get_prev, struct simple_track, node)
33 GENERIC_ITER_NEXT(simple_track_get_next, struct simple_track, node)
35 int simple_track_search_get_current(void *data, struct iter *iter)
37 return window_get_sel(data, iter);
40 int simple_track_search_matches(void *data, struct iter *iter, const char *text)
42 unsigned int flags = TI_MATCH_TITLE;
43 struct simple_track *track = iter_to_simple_track(iter);
45 if (!search_restricted)
46 flags |= TI_MATCH_ARTIST | TI_MATCH_ALBUM;
48 if (!track_info_matches(track->info, text, flags))
49 return 0;
51 window_set_sel(data, iter);
52 return 1;
55 struct shuffle_track *shuffle_list_get_next(struct list_head *head, struct shuffle_track *cur,
56 int (*filter)(const struct simple_track *))
58 struct list_head *item;
60 if (cur == NULL)
61 return to_shuffle_track(head->next);
63 item = cur->node.next;
64 again:
65 while (item != head) {
66 struct shuffle_track *track = to_shuffle_track(item);
68 if (filter((struct simple_track *)track))
69 return track;
70 item = item->next;
72 if (repeat) {
73 if (auto_reshuffle)
74 reshuffle(head);
75 item = head->next;
76 goto again;
78 return NULL;
81 struct shuffle_track *shuffle_list_get_prev(struct list_head *head, struct shuffle_track *cur,
82 int (*filter)(const struct simple_track *))
84 struct list_head *item;
86 if (cur == NULL)
87 return to_shuffle_track(head->next);
89 item = cur->node.prev;
90 again:
91 while (item != head) {
92 struct shuffle_track *track = to_shuffle_track(item);
94 if (filter((struct simple_track *)track))
95 return track;
96 item = item->prev;
98 if (repeat) {
99 if (auto_reshuffle)
100 reshuffle(head);
101 item = head->prev;
102 goto again;
104 return NULL;
107 struct simple_track *simple_list_get_next(struct list_head *head, struct simple_track *cur,
108 int (*filter)(const struct simple_track *))
110 struct list_head *item;
112 if (cur == NULL)
113 return to_simple_track(head->next);
115 item = cur->node.next;
116 again:
117 while (item != head) {
118 struct simple_track *track = to_simple_track(item);
120 if (filter(track))
121 return track;
122 item = item->next;
124 item = head->next;
125 if (repeat)
126 goto again;
127 return NULL;
130 struct simple_track *simple_list_get_prev(struct list_head *head, struct simple_track *cur,
131 int (*filter)(const struct simple_track *))
133 struct list_head *item;
135 if (cur == NULL)
136 return to_simple_track(head->next);
138 item = cur->node.prev;
139 again:
140 while (item != head) {
141 struct simple_track *track = to_simple_track(item);
143 if (filter(track))
144 return track;
145 item = item->prev;
147 item = head->prev;
148 if (repeat)
149 goto again;
150 return NULL;
153 void sorted_list_add_track(struct list_head *head, struct simple_track *track, const char * const *keys)
155 struct list_head *item;
157 /* It is _much_ faster to iterate in reverse order because playlist
158 * file is usually sorted.
160 item = head->prev;
161 while (item != head) {
162 const struct simple_track *a = to_simple_track(&track->node);
163 const struct simple_track *b = to_simple_track(item);
165 if (track_info_cmp(a->info, b->info, keys) >= 0)
166 break;
167 item = item->prev;
169 /* add after item */
170 list_add(&track->node, item);
173 void list_add_rand(struct list_head *head, struct list_head *node, int nr)
175 struct list_head *item;
176 int pos;
178 pos = rand() % (nr + 1);
179 item = head;
180 if (pos <= nr / 2) {
181 while (pos) {
182 item = item->next;
183 pos--;
185 /* add after item */
186 list_add(node, item);
187 } else {
188 pos = nr - pos;
189 while (pos) {
190 item = item->prev;
191 pos--;
193 /* add before item */
194 list_add_tail(node, item);
198 void reshuffle(struct list_head *head)
200 struct list_head *item, *last;
201 int i = 0;
203 if (list_empty(head))
204 return;
206 last = head->prev;
207 item = head->next;
208 list_init(head);
210 while (1) {
211 struct list_head *next = item->next;
213 list_add_rand(head, item, i++);
214 if (item == last)
215 break;
216 item = next;
220 int simple_list_for_each_marked(struct list_head *head,
221 int (*cb)(void *data, struct track_info *ti), void *data, int reverse)
223 struct simple_track *t;
224 int rc = 0;
226 if (reverse) {
227 list_for_each_entry_reverse(t, head, node) {
228 if (t->marked) {
229 rc = cb(data, t->info);
230 if (rc)
231 break;
234 } else {
235 list_for_each_entry(t, head, node) {
236 if (t->marked) {
237 rc = cb(data, t->info);
238 if (rc)
239 break;
243 return rc;