1 /*****************************************************************************
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 *****************************************************************************/
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
);
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");
64 case VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
:
65 state_text
= N_("On");
68 vlc_player_osd_Message(playlist
->player
,
69 _("Random: %s"), vlc_gettext(state_text
));
70 /* vlc_player_osd_Message() does nothing in tests */
71 VLC_UNUSED(state_text
);
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");
98 case VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
:
99 state_text
= N_("All");
101 case VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT
:
102 state_text
= N_("One");
105 vlc_player_osd_Message(playlist
->player
,
106 _("Loop: %s"), vlc_gettext(state_text
));
107 /* vlc_player_osd_Message() 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
;
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
)
134 playlist
->repeat
= repeat
;
135 vlc_playlist_PlaybackRepeatChanged(playlist
);
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
)
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
159 return vlc_player_SetCurrentMedia(playlist
->player
, media
);
163 vlc_playlist_NormalOrderHasPrev(vlc_playlist_t
*playlist
)
165 if (playlist
->current
== -1)
168 if (playlist
->repeat
== VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
)
169 return playlist
->items
.size
> 0;
171 return playlist
->current
> 0;
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;
187 vlc_assert_unreachable();
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;
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)
210 return playlist
->current
+ 1;
211 case VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
:
212 if (playlist
->items
.size
== 0)
214 return (playlist
->current
+ 1) % playlist
->items
.size
;
216 vlc_assert_unreachable();
221 vlc_playlist_RandomOrderHasPrev(vlc_playlist_t
*playlist
)
223 return randomizer_HasPrev(&playlist
->randomizer
);
227 vlc_playlist_RandomOrderGetPrevIndex(vlc_playlist_t
*playlist
)
229 vlc_playlist_item_t
*prev
= randomizer_PeekPrev(&playlist
->randomizer
);
231 ssize_t index
= vlc_playlist_IndexOf(playlist
, prev
);
233 return (size_t) index
;
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
);
245 vlc_playlist_RandomOrderGetNextIndex(vlc_playlist_t
*playlist
)
247 vlc_playlist_item_t
*next
= randomizer_PeekNext(&playlist
->randomizer
);
249 ssize_t index
= vlc_playlist_IndexOf(playlist
, next
);
251 return (size_t) index
;
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
);
265 vlc_assert_unreachable();
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
);
280 vlc_assert_unreachable();
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
);
295 vlc_assert_unreachable();
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
);
310 vlc_assert_unreachable();
315 vlc_playlist_GetCurrentIndex(vlc_playlist_t
*playlist
)
317 vlc_playlist_AssertLocked(playlist
);
318 return playlist
->current
;
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
);
335 vlc_playlist_HasPrev(vlc_playlist_t
*playlist
)
337 vlc_playlist_AssertLocked(playlist
);
338 return playlist
->has_prev
;
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
))
356 ssize_t index
= vlc_playlist_GetPrevIndex(playlist
);
359 int ret
= vlc_playlist_SetCurrentMedia(playlist
, index
);
360 if (ret
!= VLC_SUCCESS
)
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_osd_Message(playlist
->player
, _("Previous"));
377 vlc_playlist_Next(vlc_playlist_t
*playlist
)
379 vlc_playlist_AssertLocked(playlist
);
381 if (!vlc_playlist_ComputeHasNext(playlist
))
384 ssize_t index
= vlc_playlist_GetNextIndex(playlist
);
387 int ret
= vlc_playlist_SetCurrentMedia(playlist
, index
);
388 if (ret
!= VLC_SUCCESS
)
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_osd_Message(playlist
->player
, _("Next"));
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
)
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
);
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
))
432 return vlc_playlist_GetNextIndex(playlist
);
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
);
445 input_item_t
*media
= playlist
->items
.data
[index
]->media
;
446 input_item_Hold(media
);