1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | #include "player.h" |
18 | |
19 | |
20 | player_backend_t player; |
21 | player_info_t player_info; |
22 | |
23 | |
24 | |
25 | static void callback_playnext() { player_skip_song(1); } |
26 | |
27 | static void |
28 | callback_fatal(char *fmt, ...) |
29 | { |
30 | va_list ap; |
31 | |
32 | ui_destroy(); |
33 | |
34 | fprintf(stderr(&__sF[2]),"The player-backend '%s' has experienced a fatal error:\n", |
35 | player.name); |
36 | |
37 | va_start(ap, fmt)__builtin_va_start(ap, fmt); |
38 | vfprintf(stderr(&__sF[2]), fmt, ap); |
39 | va_end(ap)__builtin_va_end(ap); |
40 | |
41 | fflush(stderr(&__sF[2])); |
42 | |
43 | VSIG_QUIT = 1; |
44 | exit(1); |
45 | } |
46 | |
47 | |
48 | |
49 | const player_backend_t PlayerBackends[] = { |
50 | { |
51 | BACKEND_MPLAYER, "mplayer", false0, NULL((void *)0), |
52 | mplayer_start, |
53 | mplayer_finish, |
54 | mplayer_sigchld, |
55 | mplayer_play, |
56 | mplayer_stop, |
57 | mplayer_pause, |
58 | mplayer_seek, |
59 | mplayer_volume_step, |
60 | mplayer_get_position, |
61 | mplayer_get_volume, |
62 | mplayer_is_playing, |
63 | mplayer_is_paused, |
64 | mplayer_set_callback_playnext, |
65 | mplayer_set_callback_notice, |
66 | mplayer_set_callback_error, |
67 | mplayer_set_callback_fatal, |
68 | mplayer_monitor |
69 | }, |
70 | # if defined(ENABLE_GSTREAMER) |
71 | { |
72 | BACKEND_GSTREAMER, "gst", false0, NULL((void *)0), |
73 | gstplayer_init, |
74 | gstplayer_cleanup, |
75 | NULL((void *)0), |
76 | gstplayer_play, |
77 | gstplayer_stop, |
78 | gstplayer_pause, |
79 | gstplayer_seek, |
80 | gstplayer_volume_step, |
81 | gstplayer_get_position, |
82 | gstplayer_get_volume, |
83 | gstplayer_is_playing, |
84 | gstplayer_is_paused, |
85 | gstplayer_set_callback_playnext, |
86 | gstplayer_set_callback_notice, |
87 | gstplayer_set_callback_error, |
88 | gstplayer_set_callback_fatal, |
89 | gstplayer_monitor, |
90 | }, |
91 | # endif |
92 | { 0, "", false0, NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), |
93 | NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0) } |
94 | }; |
95 | const size_t PlayerBackendsSize = sizeof(PlayerBackends) / sizeof(player_backend_t); |
96 | |
97 | |
98 | |
99 | void |
100 | player_init(const char *backend, |
101 | void (message_handler)(char *fmt, ...), |
102 | void (error_handler)(char *fmt, ...)) |
103 | { |
104 | bool_Bool found; |
105 | size_t i; |
106 | |
107 | player_info.mode = MODE_LINEAR; |
108 | player_info.queue = NULL((void *)0); |
109 | player_info.qidx = -1; |
110 | |
111 | player_info.rseed = time(0); |
112 | srand(player_info.rseed); |
113 | |
114 | |
115 | found = false0; |
116 | for (i = 0; i < PlayerBackendsSize && !found; i++) { |
117 | if (!strcasecmp(backend, PlayerBackends[i].name)) { |
118 | player = PlayerBackends[i]; |
119 | found = true1; |
120 | } |
121 | } |
122 | |
123 | if (!found) |
124 | errx(1, "media backend '%s' is unknown", backend); |
125 | |
126 | if (player.dynamic) { |
127 | ui_destroy(); |
128 | errx(1, "dynamically loaded backends not yet supported"); |
129 | } |
130 | |
131 | player.set_callback_playnext(callback_playnext); |
132 | player.set_callback_notice(message_handler); |
133 | player.set_callback_error(error_handler); |
134 | player.set_callback_fatal(callback_fatal); |
135 | player.start(); |
136 | } |
137 | |
138 | void |
139 | player_destroy() |
140 | { |
141 | player.finish(); |
142 | } |
143 | |
144 | void |
145 | player_set_queue(playlist *queue, int pos) |
146 | { |
147 | player_info.queue = queue; |
148 | player_info.qidx = pos; |
149 | } |
150 | |
151 | void |
152 | player_play() |
153 | { |
154 | if (player_info.queue == NULL((void *)0)) |
| 9 | | Assuming pointer value is null | |
|
| |
155 | errx(1, "player_play: bad queue/qidx"); |
156 | |
157 | if (player_info.qidx < 0 || player_info.qidx > player_info.queue->nfiles) |
| 11 | | Access to field 'nfiles' results in a dereference of a null pointer (loaded from field 'queue') |
|
158 | errx(1, "player_play: qidx %i out-of-range", player_info.qidx); |
159 | |
160 | player.play(player_info.queue->files[player_info.qidx]->filename); |
161 | |
162 | } |
163 | |
164 | void |
165 | player_stop() |
166 | { |
167 | player.stop(); |
168 | } |
169 | |
170 | void |
171 | player_pause() |
172 | { |
173 | if (!player.playing()) |
174 | return; |
175 | |
176 | player.pause(); |
177 | } |
178 | |
179 | void |
180 | player_seek(int seconds) |
181 | { |
182 | if (!player.playing()) |
183 | return; |
184 | |
185 | player.seek(seconds); |
186 | } |
187 | |
188 | |
189 | void |
190 | player_play_next_song(int skip) |
191 | { |
192 | if (!player.playing()) |
193 | return; |
194 | |
195 | switch (player_info.mode) { |
196 | case MODE_LINEAR: |
197 | player_info.qidx += skip; |
198 | if (player_info.qidx >= player_info.queue->nfiles) { |
199 | player_info.qidx = 0; |
200 | player_stop(); |
201 | } else |
202 | player_play(); |
203 | |
204 | break; |
205 | |
206 | case MODE_LOOP: |
207 | player_info.qidx += skip; |
208 | if (player_info.qidx >= player_info.queue->nfiles) |
209 | player_info.qidx %= player_info.queue->nfiles; |
210 | |
211 | player_play(); |
212 | break; |
213 | |
214 | case MODE_RANDOM: |
215 | player_info.qidx = rand() % player_info.queue->nfiles; |
216 | player_play(); |
217 | break; |
218 | } |
219 | } |
220 | |
221 | |
222 | void |
223 | player_play_prev_song(int skip) |
224 | { |
225 | if (!player.playing()) |
| 4 | | Value assigned to 'player_info.queue' | |
|
| |
226 | return; |
227 | |
228 | switch (player_info.mode) { |
| 6 | | Control jumps to 'case MODE_LINEAR:' at line 229 | |
|
229 | case MODE_LINEAR: |
230 | player_info.qidx -= skip; |
231 | if (player_info.qidx < 0) { |
| |
232 | player_info.qidx = 0; |
233 | player_stop(); |
234 | } else |
235 | player_play(); |
| |
236 | |
237 | break; |
238 | |
239 | case MODE_LOOP: |
240 | skip %= player_info.queue->nfiles; |
241 | if (skip <= player_info.qidx) |
242 | player_info.qidx -= skip; |
243 | else |
244 | player_info.qidx = player_info.queue->nfiles - (skip + player_info.qidx); |
245 | |
246 | player_play(); |
247 | break; |
248 | |
249 | case MODE_RANDOM: |
250 | player_info.qidx = rand() % player_info.queue->nfiles; |
251 | player_play(); |
252 | break; |
253 | } |
254 | } |
255 | |
256 | |
257 | void |
258 | player_skip_song(int num) |
259 | { |
260 | if (num >= 0) |
| |
| |
261 | player_play_next_song(num); |
262 | else |
263 | player_play_prev_song(num * -1); |
| 3 | | Calling 'player_play_prev_song' | |
|
264 | } |
265 | |
266 | void |
267 | player_volume_step(float percent) |
268 | { |
269 | if (!player.playing()) |
270 | return; |
271 | |
272 | player.volume_step(percent); |
273 | } |
274 | |
275 | void |
276 | player_monitor(void) |
277 | { |
278 | player.monitor(); |
279 | } |
280 | |