demux: mp4: set bitmap mask when possible
[vlc.git] / src / playlist / control.c
blobeb1ee18a52d0beefff249f45a42f408ef70678a6
1 /*****************************************************************************
2 * playlist/control.c
3 *****************************************************************************
4 * Copyright (C) 2018 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include "control.h"
27 #include "item.h"
28 #include "notify.h"
29 #include "playlist.h"
30 #include "player.h"
32 static void
33 vlc_playlist_PlaybackOrderChanged(vlc_playlist_t *playlist)
35 if (playlist->order == VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM)
37 /* randomizer is expected to be empty at this point */
38 assert(randomizer_Count(&playlist->randomizer) == 0);
39 randomizer_Add(&playlist->randomizer, playlist->items.data,
40 playlist->items.size);
42 bool loop = playlist->repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_ALL;
43 randomizer_SetLoop(&playlist->randomizer, loop);
45 else
46 /* we don't use the randomizer anymore */
47 randomizer_Clear(&playlist->randomizer);
49 struct vlc_playlist_state state;
50 vlc_playlist_state_Save(playlist, &state);
52 playlist->has_prev = vlc_playlist_ComputeHasPrev(playlist);
53 playlist->has_next = vlc_playlist_ComputeHasNext(playlist);
55 vlc_playlist_Notify(playlist, on_playback_order_changed, playlist->order);
56 vlc_playlist_state_NotifyChanges(playlist, &state);
58 char const *state_text = NULL;
59 switch (playlist->order)
61 case VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL:
62 state_text = N_("Off");
63 break;
64 case VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM:
65 state_text = N_("On");
66 break;
68 vlc_player_vout_OSDMessage(playlist->player,
69 _("Random: %s"), vlc_gettext(state_text));
70 /* vlc_player_vout_OSDMessage() does nothing in tests */
71 VLC_UNUSED(state_text);
74 static void
75 vlc_playlist_PlaybackRepeatChanged(vlc_playlist_t *playlist)
77 if (playlist->order == VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM)
79 bool loop = playlist->repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_ALL;
80 randomizer_SetLoop(&playlist->randomizer, loop);
83 struct vlc_playlist_state state;
84 vlc_playlist_state_Save(playlist, &state);
86 playlist->has_prev = vlc_playlist_ComputeHasPrev(playlist);
87 playlist->has_next = vlc_playlist_ComputeHasNext(playlist);
89 vlc_playlist_Notify(playlist, on_playback_repeat_changed, playlist->repeat);
90 vlc_playlist_state_NotifyChanges(playlist, &state);
92 char const *state_text = NULL;
93 switch (playlist->repeat)
95 case VLC_PLAYLIST_PLAYBACK_REPEAT_NONE:
96 state_text = N_("Off");
97 break;
98 case VLC_PLAYLIST_PLAYBACK_REPEAT_ALL:
99 state_text = N_("All");
100 break;
101 case VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT:
102 state_text = N_("One");
103 break;
105 vlc_player_vout_OSDMessage(playlist->player,
106 _("Loop: %s"), vlc_gettext(state_text));
107 /* vlc_player_vout_OSDMessage() does nothing in tests */
108 VLC_UNUSED(state_text);
111 enum vlc_playlist_playback_repeat
112 vlc_playlist_GetPlaybackRepeat(vlc_playlist_t *playlist)
114 vlc_playlist_AssertLocked(playlist);
115 return playlist->repeat;
118 enum vlc_playlist_playback_order
119 vlc_playlist_GetPlaybackOrder(vlc_playlist_t *playlist)
121 vlc_playlist_AssertLocked(playlist);
122 return playlist->order;
125 void
126 vlc_playlist_SetPlaybackRepeat(vlc_playlist_t *playlist,
127 enum vlc_playlist_playback_repeat repeat)
129 vlc_playlist_AssertLocked(playlist);
131 if (playlist->repeat == repeat)
132 return;
134 playlist->repeat = repeat;
135 vlc_playlist_PlaybackRepeatChanged(playlist);
138 void
139 vlc_playlist_SetPlaybackOrder(vlc_playlist_t *playlist,
140 enum vlc_playlist_playback_order order)
142 vlc_playlist_AssertLocked(playlist);
144 if (playlist->order == order)
145 return;
147 playlist->order = order;
148 vlc_playlist_PlaybackOrderChanged(playlist);
152 vlc_playlist_SetCurrentMedia(vlc_playlist_t *playlist, ssize_t index)
154 vlc_playlist_AssertLocked(playlist);
156 input_item_t *media = index != -1
157 ? playlist->items.data[index]->media
158 : NULL;
159 return vlc_player_SetCurrentMedia(playlist->player, media);
162 static inline bool
163 vlc_playlist_NormalOrderHasPrev(vlc_playlist_t *playlist)
165 if (playlist->current == -1)
166 return false;
168 if (playlist->repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_ALL)
169 return playlist->items.size > 0;
171 return playlist->current > 0;
174 static inline size_t
175 vlc_playlist_NormalOrderGetPrevIndex(vlc_playlist_t *playlist)
177 switch (playlist->repeat)
179 case VLC_PLAYLIST_PLAYBACK_REPEAT_NONE:
180 case VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT:
181 return playlist->current - 1;
182 case VLC_PLAYLIST_PLAYBACK_REPEAT_ALL:
183 if (playlist->current == 0)
184 return playlist->items.size - 1;
185 return playlist->current - 1;
186 default:
187 vlc_assert_unreachable();
191 static inline bool
192 vlc_playlist_NormalOrderHasNext(vlc_playlist_t *playlist)
194 if (playlist->repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_ALL)
195 return playlist->items.size > 0;
197 /* also works if current == -1 or playlist->items.size == 0 */
198 return playlist->current < (ssize_t) playlist->items.size - 1;
201 static inline size_t
202 vlc_playlist_NormalOrderGetNextIndex(vlc_playlist_t *playlist)
204 switch (playlist->repeat)
206 case VLC_PLAYLIST_PLAYBACK_REPEAT_NONE:
207 case VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT:
208 if (playlist->current >= (ssize_t) playlist->items.size - 1)
209 return -1;
210 return playlist->current + 1;
211 case VLC_PLAYLIST_PLAYBACK_REPEAT_ALL:
212 if (playlist->items.size == 0)
213 return -1;
214 return (playlist->current + 1) % playlist->items.size;
215 default:
216 vlc_assert_unreachable();
220 static inline bool
221 vlc_playlist_RandomOrderHasPrev(vlc_playlist_t *playlist)
223 return randomizer_HasPrev(&playlist->randomizer);
226 static inline size_t
227 vlc_playlist_RandomOrderGetPrevIndex(vlc_playlist_t *playlist)
229 vlc_playlist_item_t *prev = randomizer_PeekPrev(&playlist->randomizer);
230 assert(prev);
231 ssize_t index = vlc_playlist_IndexOf(playlist, prev);
232 assert(index != -1);
233 return (size_t) index;
236 static inline bool
237 vlc_playlist_RandomOrderHasNext(vlc_playlist_t *playlist)
239 if (playlist->repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_ALL)
240 return playlist->items.size > 0;
241 return randomizer_HasNext(&playlist->randomizer);
244 static inline size_t
245 vlc_playlist_RandomOrderGetNextIndex(vlc_playlist_t *playlist)
247 vlc_playlist_item_t *next = randomizer_PeekNext(&playlist->randomizer);
248 assert(next);
249 ssize_t index = vlc_playlist_IndexOf(playlist, next);
250 assert(index != -1);
251 return (size_t) index;
254 static size_t
255 vlc_playlist_GetPrevIndex(vlc_playlist_t *playlist)
257 vlc_playlist_AssertLocked(playlist);
258 switch (playlist->order)
260 case VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL:
261 return vlc_playlist_NormalOrderGetPrevIndex(playlist);
262 case VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM:
263 return vlc_playlist_RandomOrderGetPrevIndex(playlist);
264 default:
265 vlc_assert_unreachable();
269 static size_t
270 vlc_playlist_GetNextIndex(vlc_playlist_t *playlist)
272 vlc_playlist_AssertLocked(playlist);
273 switch (playlist->order)
275 case VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL:
276 return vlc_playlist_NormalOrderGetNextIndex(playlist);
277 case VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM:
278 return vlc_playlist_RandomOrderGetNextIndex(playlist);
279 default:
280 vlc_assert_unreachable();
284 bool
285 vlc_playlist_ComputeHasPrev(vlc_playlist_t *playlist)
287 vlc_playlist_AssertLocked(playlist);
288 switch (playlist->order)
290 case VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL:
291 return vlc_playlist_NormalOrderHasPrev(playlist);
292 case VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM:
293 return vlc_playlist_RandomOrderHasPrev(playlist);
294 default:
295 vlc_assert_unreachable();
299 bool
300 vlc_playlist_ComputeHasNext(vlc_playlist_t *playlist)
302 vlc_playlist_AssertLocked(playlist);
303 switch (playlist->order)
305 case VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL:
306 return vlc_playlist_NormalOrderHasNext(playlist);
307 case VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM:
308 return vlc_playlist_RandomOrderHasNext(playlist);
309 default:
310 vlc_assert_unreachable();
314 ssize_t
315 vlc_playlist_GetCurrentIndex(vlc_playlist_t *playlist)
317 vlc_playlist_AssertLocked(playlist);
318 return playlist->current;
321 static void
322 vlc_playlist_SetCurrentIndex(vlc_playlist_t *playlist, ssize_t index)
324 struct vlc_playlist_state state;
325 vlc_playlist_state_Save(playlist, &state);
327 playlist->current = index;
328 playlist->has_prev = vlc_playlist_ComputeHasPrev(playlist);
329 playlist->has_next = vlc_playlist_ComputeHasNext(playlist);
331 vlc_playlist_state_NotifyChanges(playlist, &state);
334 bool
335 vlc_playlist_HasPrev(vlc_playlist_t *playlist)
337 vlc_playlist_AssertLocked(playlist);
338 return playlist->has_prev;
341 bool
342 vlc_playlist_HasNext(vlc_playlist_t *playlist)
344 vlc_playlist_AssertLocked(playlist);
345 return playlist->has_next;
349 vlc_playlist_Prev(vlc_playlist_t *playlist)
351 vlc_playlist_AssertLocked(playlist);
353 if (!vlc_playlist_ComputeHasPrev(playlist))
354 return VLC_EGENERIC;
356 ssize_t index = vlc_playlist_GetPrevIndex(playlist);
357 assert(index != -1);
359 int ret = vlc_playlist_SetCurrentMedia(playlist, index);
360 if (ret != VLC_SUCCESS)
361 return ret;
363 if (playlist->order == VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM)
365 /* mark the item as selected in the randomizer */
366 vlc_playlist_item_t *selected = randomizer_Prev(&playlist->randomizer);
367 assert(selected == playlist->items.data[index]);
368 VLC_UNUSED(selected);
371 vlc_playlist_SetCurrentIndex(playlist, index);
372 vlc_player_vout_OSDMessage(playlist->player, _("Previous"));
373 return VLC_SUCCESS;
377 vlc_playlist_Next(vlc_playlist_t *playlist)
379 vlc_playlist_AssertLocked(playlist);
381 if (!vlc_playlist_ComputeHasNext(playlist))
382 return VLC_EGENERIC;
384 ssize_t index = vlc_playlist_GetNextIndex(playlist);
385 assert(index != -1);
387 int ret = vlc_playlist_SetCurrentMedia(playlist, index);
388 if (ret != VLC_SUCCESS)
389 return ret;
391 if (playlist->order == VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM)
393 /* mark the item as selected in the randomizer */
394 vlc_playlist_item_t *selected = randomizer_Next(&playlist->randomizer);
395 assert(selected == playlist->items.data[index]);
396 VLC_UNUSED(selected);
399 vlc_playlist_SetCurrentIndex(playlist, index);
400 vlc_player_vout_OSDMessage(playlist->player, _("Next"));
401 return VLC_SUCCESS;
405 vlc_playlist_GoTo(vlc_playlist_t *playlist, ssize_t index)
407 vlc_playlist_AssertLocked(playlist);
408 assert(index == -1 || (size_t) index < playlist->items.size);
410 int ret = vlc_playlist_SetCurrentMedia(playlist, index);
411 if (ret != VLC_SUCCESS)
412 return ret;
414 if (index != -1 && playlist->order == VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM)
416 vlc_playlist_item_t *item = playlist->items.data[index];
417 randomizer_Select(&playlist->randomizer, item);
420 vlc_playlist_SetCurrentIndex(playlist, index);
421 return VLC_SUCCESS;
424 static ssize_t
425 vlc_playlist_GetNextMediaIndex(vlc_playlist_t *playlist)
427 vlc_playlist_AssertLocked(playlist);
428 if (playlist->repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT)
429 return playlist->current;
430 if (!vlc_playlist_ComputeHasNext(playlist))
431 return -1;
432 return vlc_playlist_GetNextIndex(playlist);
435 input_item_t *
436 vlc_playlist_GetNextMedia(vlc_playlist_t *playlist)
438 /* the playlist and the player share the lock */
439 vlc_playlist_AssertLocked(playlist);
441 ssize_t index = vlc_playlist_GetNextMediaIndex(playlist);
442 if (index == -1)
443 return NULL;
445 input_item_t *media = playlist->items.data[index]->media;
446 input_item_Hold(media);
447 return media;