1 /*
2 * Copyright (c) 2011 Tim van der Molen <tim@kariliq.nl>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <pthread.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "siren.h"
22
23 static int queue_search_entry(const void *, const char *);
24
25 static pthread_mutex_t queue_menu_mtx = PTHREAD_MUTEX_INITIALIZER;
26 static struct format *queue_altformat;
27 static struct format *queue_format;
28 static struct menu *queue_menu;
29 static unsigned int queue_duration;
30
31 void
queue_activate_entry(void)32 queue_activate_entry(void)
33 {
34 struct track *t;
35
36 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
37 if ((t = menu_get_selected_entry_data(queue_menu)) != NULL) {
38 queue_duration -= t->duration;
39 menu_remove_selected_entry(queue_menu);
40 }
41 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
42
43 if (t != NULL) {
44 player_play_track(t);
45 queue_print();
46 }
47 }
48
49 void
queue_add_dir(const char * path)50 queue_add_dir(const char *path)
51 {
52 struct dir *d;
53 struct dir_entry *de;
54 struct track *t;
55
56 if ((d = dir_open(path)) == NULL) {
57 msg_err("%s", path);
58 return;
59 }
60
61 while ((de = dir_get_entry(d)) != NULL)
62 switch (de->type) {
63 case FILE_TYPE_DIRECTORY:
64 if (strcmp(de->name, ".") && strcmp(de->name, ".."))
65 queue_add_dir(de->path);
66 break;
67 case FILE_TYPE_REGULAR:
68 if ((t = track_get(de->path, NULL)) != NULL)
69 queue_add_track(t);
70 break;
71 default:
72 msg_errx("%s: Unsupported file type", de->path);
73 break;
74 }
75
76 dir_close(d);
77 }
78
79 void
queue_add_track(struct track * t)80 queue_add_track(struct track *t)
81 {
82 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
83 menu_insert_tail(queue_menu, t);
84 queue_duration += t->duration;
85 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
86 queue_print();
87 }
88
89 void
queue_copy_entry(enum view_id view)90 queue_copy_entry(enum view_id view)
91 {
92 struct track *t;
93
94 if (view == VIEW_ID_QUEUE)
95 return;
96
97 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
98 if ((t = menu_get_selected_entry_data(queue_menu)) != NULL)
99 view_add_track(view, t);
100 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
101 }
102
103 void
queue_delete_all_entries(void)104 queue_delete_all_entries(void)
105 {
106 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
107 menu_remove_all_entries(queue_menu);
108 queue_duration = 0;
109 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
110 queue_print();
111 }
112
113 void
queue_delete_entry(void)114 queue_delete_entry(void)
115 {
116 struct track *t;
117
118 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
119 if ((t = menu_get_selected_entry_data(queue_menu)) != NULL) {
120 queue_duration -= t->duration;
121 menu_remove_selected_entry(queue_menu);
122 }
123 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
124 queue_print();
125 }
126
127 void
queue_end(void)128 queue_end(void)
129 {
130 menu_free(queue_menu);
131 }
132
133 static void
queue_get_entry_text(const void * e,char * buf,size_t bufsize)134 queue_get_entry_text(const void *e, char *buf, size_t bufsize)
135 {
136 const struct track *t;
137
138 t = e;
139 format_track_snprintf(buf, bufsize, queue_format, queue_altformat, t);
140 }
141
142 struct track *
queue_get_next_track(void)143 queue_get_next_track(void)
144 {
145 struct menu_entry *me;
146 struct track *t;
147
148 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
149 if ((me = menu_get_first_entry(queue_menu)) == NULL)
150 t = NULL;
151 else {
152 t = menu_get_entry_data(me);
153 queue_duration -= t->duration;
154 menu_remove_entry(queue_menu, me);
155 }
156 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
157
158 if (t != NULL)
159 queue_print();
160
161 return t;
162 }
163
164 void
queue_init(void)165 queue_init(void)
166 {
167 queue_menu = menu_init(NULL, queue_get_entry_text, queue_search_entry);
168 }
169
170 void
queue_move_entry_down(void)171 queue_move_entry_down(void)
172 {
173 struct menu_entry *e;
174
175 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
176 if ((e = menu_get_selected_entry(queue_menu)) != NULL)
177 menu_move_entry_down(queue_menu, e);
178 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
179 queue_print();
180 }
181
182 void
queue_move_entry_up(void)183 queue_move_entry_up(void)
184 {
185 struct menu_entry *e;
186
187 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
188 if ((e = menu_get_selected_entry(queue_menu)) != NULL)
189 menu_move_entry_up(queue_menu, e);
190 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
191 queue_print();
192 }
193
194 void
queue_print(void)195 queue_print(void)
196 {
197 if (view_get_id() != VIEW_ID_QUEUE)
198 return;
199
200 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
201 screen_view_title_printf("Queue: %u track%s (%u:%02u:%02u)",
202 menu_get_nentries(queue_menu),
203 menu_get_nentries(queue_menu) == 1 ? "" : "s",
204 HOURS(queue_duration),
205 HMINS(queue_duration),
206 MSECS(queue_duration));
207 option_lock();
208 queue_format = option_get_format("queue-format");
209 queue_altformat = option_get_format("queue-format-alt");
210 menu_print(queue_menu);
211 option_unlock();
212 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
213 }
214
215 void
queue_scroll_down(enum menu_scroll scroll)216 queue_scroll_down(enum menu_scroll scroll)
217 {
218 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
219 menu_scroll_down(queue_menu, scroll);
220 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
221 queue_print();
222 }
223
224 void
queue_scroll_up(enum menu_scroll scroll)225 queue_scroll_up(enum menu_scroll scroll)
226 {
227 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
228 menu_scroll_up(queue_menu, scroll);
229 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
230 queue_print();
231 }
232
233 static int
queue_search_entry(const void * e,const char * search)234 queue_search_entry(const void *e, const char *search)
235 {
236 const struct track *t;
237
238 t = e;
239 return track_search(t, search);
240 }
241
242 void
queue_search_next(const char * search)243 queue_search_next(const char *search)
244 {
245 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
246 menu_search_next(queue_menu, search);
247 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
248 queue_print();
249 }
250
251 void
queue_search_prev(const char * search)252 queue_search_prev(const char *search)
253 {
254 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
255 menu_search_prev(queue_menu, search);
256 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
257 queue_print();
258 }
259
260 void
queue_select_first_entry(void)261 queue_select_first_entry(void)
262 {
263 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
264 menu_select_first_entry(queue_menu);
265 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
266 queue_print();
267 }
268
269 void
queue_select_last_entry(void)270 queue_select_last_entry(void)
271 {
272 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
273 menu_select_last_entry(queue_menu);
274 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
275 queue_print();
276 }
277
278 void
queue_select_next_entry(void)279 queue_select_next_entry(void)
280 {
281 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
282 menu_select_next_entry(queue_menu);
283 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
284 queue_print();
285 }
286
287 void
queue_select_prev_entry(void)288 queue_select_prev_entry(void)
289 {
290 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
291 menu_select_prev_entry(queue_menu);
292 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
293 queue_print();
294 }
295
296 /* Recalculate the duration. */
297 void
queue_update(void)298 queue_update(void)
299 {
300 struct menu_entry *e;
301 struct track *t;
302
303 XPTHREAD_MUTEX_LOCK(&queue_menu_mtx);
304 queue_duration = 0;
305 MENU_FOR_EACH_ENTRY(queue_menu, e) {
306 t = menu_get_entry_data(e);
307 queue_duration += t->duration;
308 }
309 XPTHREAD_MUTEX_UNLOCK(&queue_menu_mtx);
310 }
311