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 *****************************************************************************/
32 /* the playlist lock is the one of the player */
33 # define vlc_playlist_Lock(p) VLC_UNUSED(p);
34 # define vlc_playlist_Unlock(p) VLC_UNUSED(p);
37 CreateDummyMedia(int num
)
42 int res
= asprintf(&url
, "vlc://item-%d", num
);
46 res
= asprintf(&name
, "item-%d", num
);
50 input_item_t
*media
= input_item_New(url
, name
);
57 CreateDummyMediaArray(input_item_t
*out
[], size_t count
)
59 for (size_t i
= 0; i
< count
; ++i
)
61 out
[i
] = CreateDummyMedia(i
);
67 DestroyMediaArray(input_item_t
*const array
[], size_t count
)
69 for (size_t i
= 0; i
< count
; ++i
)
70 input_item_Release(array
[i
]);
73 #define EXPECT_AT(index, id) \
74 assert(vlc_playlist_Get(playlist, index)->media == media[id])
79 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
82 input_item_t
*media
[10];
83 CreateDummyMediaArray(media
, 10);
85 /* append one by one */
86 for (int i
= 0; i
< 5; ++i
)
88 int ret
= vlc_playlist_AppendOne(playlist
, media
[i
]);
89 assert(ret
== VLC_SUCCESS
);
92 /* append several at once */
93 int ret
= vlc_playlist_Append(playlist
, &media
[5], 5);
94 assert(ret
== VLC_SUCCESS
);
96 assert(vlc_playlist_Count(playlist
) == 10);
108 DestroyMediaArray(media
, 10);
109 vlc_playlist_Delete(playlist
);
115 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
118 input_item_t
*media
[15];
119 CreateDummyMediaArray(media
, 15);
121 /* initial playlist with 5 items */
122 int ret
= vlc_playlist_Append(playlist
, media
, 5);
123 assert(ret
== VLC_SUCCESS
);
125 /* insert one by one */
126 for (int i
= 0; i
< 5; ++i
)
128 ret
= vlc_playlist_InsertOne(playlist
, 2, media
[i
+ 5]);
129 assert(ret
== VLC_SUCCESS
);
132 /* insert several at once */
133 ret
= vlc_playlist_Insert(playlist
, 6, &media
[10], 5);
134 assert(ret
== VLC_SUCCESS
);
136 assert(vlc_playlist_Count(playlist
) == 15);
157 DestroyMediaArray(media
, 15);
158 vlc_playlist_Delete(playlist
);
164 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
167 input_item_t
*media
[10];
168 CreateDummyMediaArray(media
, 10);
170 /* initial playlist with 10 items */
171 int ret
= vlc_playlist_Append(playlist
, media
, 10);
172 assert(ret
== VLC_SUCCESS
);
174 /* move slice {3, 4, 5, 6} so that its new position is 5 */
175 vlc_playlist_Move(playlist
, 3, 4, 5);
188 /* move it back to its original position */
189 vlc_playlist_Move(playlist
, 5, 4, 3);
202 DestroyMediaArray(media
, 10);
203 vlc_playlist_Delete(playlist
);
209 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
212 input_item_t
*media
[10];
213 CreateDummyMediaArray(media
, 10);
215 /* initial playlist with 10 items */
216 int ret
= vlc_playlist_Append(playlist
, media
, 10);
217 assert(ret
== VLC_SUCCESS
);
219 /* remove one by one */
220 for (int i
= 0; i
< 3; ++i
)
221 vlc_playlist_RemoveOne(playlist
, 2);
223 /* remove several at once */
224 vlc_playlist_Remove(playlist
, 3, 2);
226 assert(vlc_playlist_Count(playlist
) == 5);
233 DestroyMediaArray(media
, 10);
234 vlc_playlist_Delete(playlist
);
240 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
243 input_item_t
*media
[10];
244 CreateDummyMediaArray(media
, 10);
246 /* initial playlist with 10 items */
247 int ret
= vlc_playlist_Append(playlist
, media
, 10);
248 assert(ret
== VLC_SUCCESS
);
250 assert(vlc_playlist_Count(playlist
) == 10);
251 vlc_playlist_Clear(playlist
);
252 assert(vlc_playlist_Count(playlist
) == 0);
254 DestroyMediaArray(media
, 10);
255 vlc_playlist_Delete(playlist
);
259 test_expand_item(void)
261 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
264 input_item_t
*media
[16];
265 CreateDummyMediaArray(media
, 16);
267 /* initial playlist with 10 items */
268 int ret
= vlc_playlist_Append(playlist
, media
, 10);
269 assert(ret
== VLC_SUCCESS
);
271 /* create a subtree for item 8 with 4 children */
272 input_item_t
*item_to_expand
= playlist
->items
.data
[8]->media
;
273 input_item_node_t
*root
= input_item_node_Create(item_to_expand
);
274 for (int i
= 0; i
< 4; ++i
)
276 input_item_node_t
*node
= input_item_node_AppendItem(root
,
281 /* on the 3rd children, add 2 grand-children */
282 input_item_node_t
*parent
= root
->pp_children
[2];
283 for (int i
= 0; i
< 2; ++i
)
285 input_item_node_t
*node
= input_item_node_AppendItem(parent
,
290 playlist
->current
= 8;
291 playlist
->has_prev
= true;
292 playlist
->has_next
= true;
294 ret
= vlc_playlist_ExpandItem(playlist
, 8, root
);
295 assert(ret
== VLC_SUCCESS
);
296 assert(vlc_playlist_Count(playlist
) == 15);
310 /* item 8 will be replaced, the current must stay the same */
311 assert(playlist
->current
== 8);
313 input_item_node_Delete(root
);
314 DestroyMediaArray(media
, 16);
315 vlc_playlist_Delete(playlist
);
318 struct playlist_state
320 size_t playlist_size
;
327 playlist_state_init(struct playlist_state
*state
, vlc_playlist_t
*playlist
)
329 state
->playlist_size
= vlc_playlist_Count(playlist
);
330 state
->current
= vlc_playlist_GetCurrentIndex(playlist
);
331 state
->has_prev
= vlc_playlist_HasPrev(playlist
);
332 state
->has_next
= vlc_playlist_HasNext(playlist
);
335 struct items_reset_report
338 struct playlist_state state
;
341 struct items_added_report
345 struct playlist_state state
;
348 struct items_moved_report
353 struct playlist_state state
;
356 struct items_removed_report
360 struct playlist_state state
;
363 struct playback_repeat_changed_report
365 enum vlc_playlist_playback_repeat repeat
;
368 struct playback_order_changed_report
370 enum vlc_playlist_playback_order order
;
373 struct current_index_changed_report
378 struct has_prev_changed_report
383 struct has_next_changed_report
390 struct VLC_VECTOR(struct items_reset_report
) vec_items_reset
;
391 struct VLC_VECTOR(struct items_added_report
) vec_items_added
;
392 struct VLC_VECTOR(struct items_moved_report
) vec_items_moved
;
393 struct VLC_VECTOR(struct items_removed_report
) vec_items_removed
;
394 struct VLC_VECTOR(struct playback_order_changed_report
)
395 vec_playback_order_changed
;
396 struct VLC_VECTOR(struct playback_repeat_changed_report
)
397 vec_playback_repeat_changed
;
398 struct VLC_VECTOR(struct current_index_changed_report
)
399 vec_current_index_changed
;
400 struct VLC_VECTOR(struct has_prev_changed_report
) vec_has_prev_changed
;
401 struct VLC_VECTOR(struct has_next_changed_report
) vec_has_next_changed
;
404 #define CALLBACK_CTX_INITIALIZER \
406 VLC_VECTOR_INITIALIZER, \
407 VLC_VECTOR_INITIALIZER, \
408 VLC_VECTOR_INITIALIZER, \
409 VLC_VECTOR_INITIALIZER, \
410 VLC_VECTOR_INITIALIZER, \
411 VLC_VECTOR_INITIALIZER, \
412 VLC_VECTOR_INITIALIZER, \
413 VLC_VECTOR_INITIALIZER, \
414 VLC_VECTOR_INITIALIZER, \
418 callback_ctx_reset(struct callback_ctx
*ctx
)
420 vlc_vector_clear(&ctx
->vec_items_reset
);
421 vlc_vector_clear(&ctx
->vec_items_added
);
422 vlc_vector_clear(&ctx
->vec_items_moved
);
423 vlc_vector_clear(&ctx
->vec_items_removed
);
424 vlc_vector_clear(&ctx
->vec_playback_repeat_changed
);
425 vlc_vector_clear(&ctx
->vec_playback_order_changed
);
426 vlc_vector_clear(&ctx
->vec_current_index_changed
);
427 vlc_vector_clear(&ctx
->vec_has_prev_changed
);
428 vlc_vector_clear(&ctx
->vec_has_next_changed
);
432 callback_ctx_destroy(struct callback_ctx
*ctx
)
434 vlc_vector_destroy(&ctx
->vec_items_reset
);
435 vlc_vector_destroy(&ctx
->vec_items_added
);
436 vlc_vector_destroy(&ctx
->vec_items_moved
);
437 vlc_vector_destroy(&ctx
->vec_items_removed
);
438 vlc_vector_destroy(&ctx
->vec_playback_repeat_changed
);
439 vlc_vector_destroy(&ctx
->vec_playback_order_changed
);
440 vlc_vector_destroy(&ctx
->vec_current_index_changed
);
441 vlc_vector_destroy(&ctx
->vec_has_prev_changed
);
442 vlc_vector_destroy(&ctx
->vec_has_next_changed
);
446 callback_on_items_reset(vlc_playlist_t
*playlist
,
447 vlc_playlist_item_t
*const items
[], size_t count
,
451 struct callback_ctx
*ctx
= userdata
;
453 struct items_reset_report report
;
454 report
.count
= count
;
455 playlist_state_init(&report
.state
, playlist
);
456 vlc_vector_push(&ctx
->vec_items_reset
, report
);
460 callback_on_items_added(vlc_playlist_t
*playlist
, size_t index
,
461 vlc_playlist_item_t
*const items
[], size_t count
,
465 struct callback_ctx
*ctx
= userdata
;
467 struct items_added_report report
;
468 report
.index
= index
;
469 report
.count
= count
;
470 playlist_state_init(&report
.state
, playlist
);
471 vlc_vector_push(&ctx
->vec_items_added
, report
);
475 callback_on_items_moved(vlc_playlist_t
*playlist
, size_t index
, size_t count
,
476 size_t target
, void *userdata
)
478 struct callback_ctx
*ctx
= userdata
;
480 struct items_moved_report report
;
481 report
.index
= index
;
482 report
.count
= count
;
483 report
.target
= target
;
484 playlist_state_init(&report
.state
, playlist
);
485 vlc_vector_push(&ctx
->vec_items_moved
, report
);
489 callback_on_items_removed(vlc_playlist_t
*playlist
, size_t index
, size_t count
,
492 struct callback_ctx
*ctx
= userdata
;
494 struct items_removed_report report
;
495 report
.index
= index
;
496 report
.count
= count
;
497 playlist_state_init(&report
.state
, playlist
);
498 vlc_vector_push(&ctx
->vec_items_removed
, report
);
502 callback_on_playback_repeat_changed(vlc_playlist_t
*playlist
,
503 enum vlc_playlist_playback_repeat repeat
,
506 VLC_UNUSED(playlist
);
507 struct callback_ctx
*ctx
= userdata
;
509 struct playback_repeat_changed_report report
;
510 report
.repeat
= repeat
;
511 vlc_vector_push(&ctx
->vec_playback_repeat_changed
, report
);
515 callback_on_playback_order_changed(vlc_playlist_t
*playlist
,
516 enum vlc_playlist_playback_order order
,
519 VLC_UNUSED(playlist
);
520 struct callback_ctx
*ctx
= userdata
;
522 struct playback_order_changed_report report
;
523 report
.order
= order
;
524 vlc_vector_push(&ctx
->vec_playback_order_changed
, report
);
528 callback_on_current_index_changed(vlc_playlist_t
*playlist
, ssize_t index
,
531 VLC_UNUSED(playlist
);
532 struct callback_ctx
*ctx
= userdata
;
534 struct current_index_changed_report report
;
535 report
.current
= index
;
536 vlc_vector_push(&ctx
->vec_current_index_changed
, report
);
540 callback_on_has_prev_changed(vlc_playlist_t
*playlist
, bool has_prev
,
543 VLC_UNUSED(playlist
);
544 struct callback_ctx
*ctx
= userdata
;
546 struct has_prev_changed_report report
;
547 report
.has_prev
= has_prev
;
548 vlc_vector_push(&ctx
->vec_has_prev_changed
, report
);
552 callback_on_has_next_changed(vlc_playlist_t
*playlist
, bool has_next
,
555 VLC_UNUSED(playlist
);
556 struct callback_ctx
*ctx
= userdata
;
558 struct has_next_changed_report report
;
559 report
.has_next
= has_next
;
560 vlc_vector_push(&ctx
->vec_has_next_changed
, report
);
564 test_items_added_callbacks(void)
566 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
569 input_item_t
*media
[10];
570 CreateDummyMediaArray(media
, 10);
572 struct vlc_playlist_callbacks cbs
= {
573 .on_items_added
= callback_on_items_added
,
574 .on_current_index_changed
= callback_on_current_index_changed
,
575 .on_has_prev_changed
= callback_on_has_prev_changed
,
576 .on_has_next_changed
= callback_on_has_next_changed
,
579 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
580 vlc_playlist_listener_id
*listener
=
581 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
584 int ret
= vlc_playlist_AppendOne(playlist
, media
[0]);
585 assert(ret
== VLC_SUCCESS
);
587 /* the callbacks must be called with *all* values up to date */
588 assert(ctx
.vec_items_added
.size
== 1);
589 assert(ctx
.vec_items_added
.data
[0].index
== 0);
590 assert(ctx
.vec_items_added
.data
[0].count
== 1);
591 assert(ctx
.vec_items_added
.data
[0].state
.playlist_size
== 1);
592 assert(ctx
.vec_items_added
.data
[0].state
.current
== -1);
593 assert(!ctx
.vec_items_added
.data
[0].state
.has_prev
);
594 assert(ctx
.vec_items_added
.data
[0].state
.has_next
);
596 assert(ctx
.vec_current_index_changed
.size
== 0);
598 assert(ctx
.vec_has_prev_changed
.size
== 0);
600 assert(ctx
.vec_has_next_changed
.size
== 1);
601 assert(ctx
.vec_has_next_changed
.data
[0].has_next
);
603 callback_ctx_reset(&ctx
);
605 /* set the only item as current */
606 playlist
->current
= 0;
607 playlist
->has_prev
= false;
608 playlist
->has_next
= false;
610 /* insert before the current item */
611 ret
= vlc_playlist_Insert(playlist
, 0, &media
[1], 4);
612 assert(ret
== VLC_SUCCESS
);
614 assert(ctx
.vec_items_added
.size
== 1);
615 assert(ctx
.vec_items_added
.data
[0].index
== 0);
616 assert(ctx
.vec_items_added
.data
[0].count
== 4);
617 assert(ctx
.vec_items_added
.data
[0].state
.playlist_size
== 5);
618 assert(ctx
.vec_items_added
.data
[0].state
.current
== 4); /* shifted */
619 assert(ctx
.vec_items_added
.data
[0].state
.has_prev
);
620 assert(!ctx
.vec_items_added
.data
[0].state
.has_next
);
622 assert(ctx
.vec_current_index_changed
.size
== 1);
623 assert(ctx
.vec_current_index_changed
.data
[0].current
== 4);
625 assert(ctx
.vec_has_prev_changed
.size
== 1);
626 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
628 assert(ctx
.vec_has_next_changed
.size
== 0);
630 callback_ctx_reset(&ctx
);
632 /* append (after the current item) */
633 ret
= vlc_playlist_Append(playlist
, &media
[5], 5);
634 assert(ret
== VLC_SUCCESS
);
636 assert(ctx
.vec_items_added
.size
== 1);
637 assert(ctx
.vec_items_added
.data
[0].index
== 5);
638 assert(ctx
.vec_items_added
.data
[0].count
== 5);
639 assert(ctx
.vec_items_added
.data
[0].state
.playlist_size
== 10);
640 assert(ctx
.vec_items_added
.data
[0].state
.current
== 4);
641 assert(ctx
.vec_items_added
.data
[0].state
.has_prev
);
642 assert(ctx
.vec_items_added
.data
[0].state
.has_next
);
644 assert(ctx
.vec_current_index_changed
.size
== 0);
646 assert(ctx
.vec_has_prev_changed
.size
== 0);
648 assert(ctx
.vec_has_next_changed
.size
== 1);
649 assert(ctx
.vec_has_next_changed
.data
[0].has_next
);
651 callback_ctx_destroy(&ctx
);
652 vlc_playlist_RemoveListener(playlist
, listener
);
653 DestroyMediaArray(media
, 10);
654 vlc_playlist_Delete(playlist
);
658 test_items_moved_callbacks(void)
660 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
663 input_item_t
*media
[10];
664 CreateDummyMediaArray(media
, 10);
666 /* initial playlist with 10 items */
667 int ret
= vlc_playlist_Append(playlist
, media
, 10);
668 assert(ret
== VLC_SUCCESS
);
670 struct vlc_playlist_callbacks cbs
= {
671 .on_items_moved
= callback_on_items_moved
,
672 .on_current_index_changed
= callback_on_current_index_changed
,
673 .on_has_prev_changed
= callback_on_has_prev_changed
,
674 .on_has_next_changed
= callback_on_has_next_changed
,
677 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
678 vlc_playlist_listener_id
*listener
=
679 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
682 vlc_playlist_Move(playlist
, 2, 3, 5);
684 assert(ctx
.vec_items_moved
.size
== 1);
685 assert(ctx
.vec_items_moved
.data
[0].index
== 2);
686 assert(ctx
.vec_items_moved
.data
[0].count
== 3);
687 assert(ctx
.vec_items_moved
.data
[0].target
== 5);
688 assert(ctx
.vec_items_moved
.data
[0].state
.playlist_size
== 10);
689 assert(ctx
.vec_items_moved
.data
[0].state
.current
== -1);
690 assert(!ctx
.vec_items_moved
.data
[0].state
.has_prev
);
691 assert(ctx
.vec_items_moved
.data
[0].state
.has_next
);
693 assert(ctx
.vec_current_index_changed
.size
== 0);
694 assert(ctx
.vec_has_prev_changed
.size
== 0);
695 assert(ctx
.vec_has_next_changed
.size
== 0);
697 playlist
->current
= 3;
698 playlist
->has_prev
= true;
699 playlist
->has_next
= true;
701 callback_ctx_reset(&ctx
);
703 /* the current index belongs to the moved slice */
704 vlc_playlist_Move(playlist
, 1, 3, 5);
706 assert(ctx
.vec_items_moved
.size
== 1);
707 assert(ctx
.vec_items_moved
.data
[0].index
== 1);
708 assert(ctx
.vec_items_moved
.data
[0].count
== 3);
709 assert(ctx
.vec_items_moved
.data
[0].target
== 5);
710 assert(ctx
.vec_items_moved
.data
[0].state
.playlist_size
== 10);
711 assert(ctx
.vec_items_moved
.data
[0].state
.current
== 7);
712 assert(ctx
.vec_items_moved
.data
[0].state
.has_prev
);
713 assert(ctx
.vec_items_moved
.data
[0].state
.has_next
);
715 assert(ctx
.vec_current_index_changed
.size
== 1);
716 assert(ctx
.vec_current_index_changed
.data
[0].current
== 7);
718 assert(ctx
.vec_has_prev_changed
.size
== 0);
719 assert(ctx
.vec_has_next_changed
.size
== 0);
721 callback_ctx_reset(&ctx
);
723 /* as a result of this move, the current item (7) will be at index 0 */
724 vlc_playlist_Move(playlist
, 0, 7, 1);
726 assert(ctx
.vec_items_moved
.size
== 1);
727 assert(ctx
.vec_items_moved
.data
[0].index
== 0);
728 assert(ctx
.vec_items_moved
.data
[0].count
== 7);
729 assert(ctx
.vec_items_moved
.data
[0].target
== 1);
730 assert(ctx
.vec_items_moved
.data
[0].state
.playlist_size
== 10);
731 assert(ctx
.vec_items_moved
.data
[0].state
.current
== 0);
732 assert(!ctx
.vec_items_moved
.data
[0].state
.has_prev
);
733 assert(ctx
.vec_items_moved
.data
[0].state
.has_next
);
735 assert(ctx
.vec_current_index_changed
.size
== 1);
736 assert(ctx
.vec_current_index_changed
.data
[0].current
== 0);
738 assert(ctx
.vec_has_prev_changed
.size
== 1);
739 assert(!ctx
.vec_has_prev_changed
.data
[0].has_prev
);
741 assert(ctx
.vec_has_next_changed
.size
== 0);
743 callback_ctx_reset(&ctx
);
745 playlist
->current
= 5;
746 playlist
->has_prev
= true;
747 playlist
->has_next
= true;
749 vlc_playlist_Move(playlist
, 6, 2, 3);
751 assert(ctx
.vec_items_moved
.size
== 1);
752 assert(ctx
.vec_items_moved
.data
[0].index
== 6);
753 assert(ctx
.vec_items_moved
.data
[0].count
== 2);
754 assert(ctx
.vec_items_moved
.data
[0].target
== 3);
755 assert(ctx
.vec_items_moved
.data
[0].state
.playlist_size
== 10);
756 assert(ctx
.vec_items_moved
.data
[0].state
.current
== 7);
757 assert(ctx
.vec_items_moved
.data
[0].state
.has_prev
);
758 assert(ctx
.vec_items_moved
.data
[0].state
.has_next
);
760 assert(ctx
.vec_current_index_changed
.size
== 1);
761 assert(ctx
.vec_current_index_changed
.data
[0].current
== 7);
763 assert(ctx
.vec_has_prev_changed
.size
== 0);
765 assert(ctx
.vec_has_next_changed
.size
== 0);
767 callback_ctx_destroy(&ctx
);
768 vlc_playlist_RemoveListener(playlist
, listener
);
769 DestroyMediaArray(media
, 10);
770 vlc_playlist_Delete(playlist
);
774 test_items_removed_callbacks(void)
776 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
779 input_item_t
*media
[10];
780 CreateDummyMediaArray(media
, 10);
782 /* initial playlist with 10 items */
783 int ret
= vlc_playlist_Append(playlist
, media
, 10);
784 assert(ret
== VLC_SUCCESS
);
786 struct vlc_playlist_callbacks cbs
= {
787 .on_items_removed
= callback_on_items_removed
,
788 .on_current_index_changed
= callback_on_current_index_changed
,
789 .on_has_prev_changed
= callback_on_has_prev_changed
,
790 .on_has_next_changed
= callback_on_has_next_changed
,
793 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
794 vlc_playlist_listener_id
*listener
=
795 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
798 vlc_playlist_RemoveOne(playlist
, 4);
800 assert(ctx
.vec_items_removed
.size
== 1);
801 assert(ctx
.vec_items_removed
.data
[0].index
== 4);
802 assert(ctx
.vec_items_removed
.data
[0].count
== 1);
803 assert(ctx
.vec_items_removed
.data
[0].state
.playlist_size
== 9);
804 assert(ctx
.vec_items_removed
.data
[0].state
.current
== -1);
805 assert(!ctx
.vec_items_removed
.data
[0].state
.has_prev
);
806 assert(ctx
.vec_items_removed
.data
[0].state
.has_next
);
808 assert(ctx
.vec_current_index_changed
.size
== 0);
809 assert(ctx
.vec_has_prev_changed
.size
== 0);
810 assert(ctx
.vec_has_next_changed
.size
== 0);
812 playlist
->current
= 7;
813 playlist
->has_prev
= true;
814 playlist
->has_next
= true;
816 callback_ctx_reset(&ctx
);
818 /* remove items before the current */
819 vlc_playlist_Remove(playlist
, 2, 4);
821 assert(ctx
.vec_items_removed
.size
== 1);
822 assert(ctx
.vec_items_removed
.data
[0].index
== 2);
823 assert(ctx
.vec_items_removed
.data
[0].count
== 4);
824 assert(ctx
.vec_items_removed
.data
[0].state
.playlist_size
== 5);
825 assert(ctx
.vec_items_removed
.data
[0].state
.current
== 3); /* shifted */
826 assert(ctx
.vec_items_removed
.data
[0].state
.has_prev
);
827 assert(ctx
.vec_items_removed
.data
[0].state
.has_next
);
829 assert(ctx
.vec_current_index_changed
.size
== 1);
830 assert(ctx
.vec_current_index_changed
.data
[0].current
== 3);
832 assert(ctx
.vec_has_prev_changed
.size
== 0);
834 assert(ctx
.vec_has_next_changed
.size
== 0);
836 callback_ctx_reset(&ctx
);
838 /* remove the remaining items (without Clear) */
839 vlc_playlist_Remove(playlist
, 0, 5);
841 assert(ctx
.vec_items_removed
.size
== 1);
842 assert(ctx
.vec_items_removed
.data
[0].index
== 0);
843 assert(ctx
.vec_items_removed
.data
[0].count
== 5);
844 assert(ctx
.vec_items_removed
.data
[0].state
.playlist_size
== 0);
845 assert(ctx
.vec_items_removed
.data
[0].state
.current
== -1);
846 assert(!ctx
.vec_items_removed
.data
[0].state
.has_prev
);
847 assert(!ctx
.vec_items_removed
.data
[0].state
.has_next
);
849 assert(ctx
.vec_current_index_changed
.size
== 1);
850 assert(ctx
.vec_current_index_changed
.data
[0].current
== -1);
852 assert(ctx
.vec_has_prev_changed
.size
== 1);
853 assert(!ctx
.vec_has_prev_changed
.data
[0].has_prev
);
855 assert(ctx
.vec_has_next_changed
.size
== 1);
856 assert(!ctx
.vec_has_next_changed
.data
[0].has_next
);
858 callback_ctx_destroy(&ctx
);
859 vlc_playlist_RemoveListener(playlist
, listener
);
860 DestroyMediaArray(media
, 10);
861 vlc_playlist_Delete(playlist
);
865 test_items_reset_callbacks(void)
867 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
870 input_item_t
*media
[10];
871 CreateDummyMediaArray(media
, 10);
873 /* initial playlist with 10 items */
874 int ret
= vlc_playlist_Append(playlist
, media
, 10);
875 assert(ret
== VLC_SUCCESS
);
877 struct vlc_playlist_callbacks cbs
= {
878 .on_items_reset
= callback_on_items_reset
,
879 .on_current_index_changed
= callback_on_current_index_changed
,
880 .on_has_prev_changed
= callback_on_has_prev_changed
,
881 .on_has_next_changed
= callback_on_has_next_changed
,
884 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
885 vlc_playlist_listener_id
*listener
=
886 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
889 callback_ctx_reset(&ctx
);
891 playlist
->current
= 9; /* last item */
892 playlist
->has_prev
= true;
893 playlist
->has_next
= false;
895 vlc_playlist_Clear(playlist
);
897 assert(ctx
.vec_items_reset
.size
== 1);
898 assert(ctx
.vec_items_reset
.data
[0].count
== 0);
899 assert(ctx
.vec_items_reset
.data
[0].state
.playlist_size
== 0);
900 assert(ctx
.vec_items_reset
.data
[0].state
.current
== -1);
901 assert(!ctx
.vec_items_reset
.data
[0].state
.has_prev
);
902 assert(!ctx
.vec_items_reset
.data
[0].state
.has_next
);
904 assert(ctx
.vec_current_index_changed
.size
== 1);
905 assert(ctx
.vec_current_index_changed
.data
[0].current
== -1);
907 assert(ctx
.vec_has_prev_changed
.size
== 1);
908 assert(!ctx
.vec_has_prev_changed
.data
[0].has_prev
);
910 assert(ctx
.vec_has_next_changed
.size
== 0);
912 callback_ctx_destroy(&ctx
);
913 vlc_playlist_RemoveListener(playlist
, listener
);
914 DestroyMediaArray(media
, 10);
915 vlc_playlist_Delete(playlist
);
919 test_playback_repeat_changed_callbacks(void)
921 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
924 playlist
->repeat
= VLC_PLAYLIST_PLAYBACK_REPEAT_NONE
;
926 struct vlc_playlist_callbacks cbs
= {
927 .on_playback_repeat_changed
= callback_on_playback_repeat_changed
,
930 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
931 vlc_playlist_listener_id
*listener
=
932 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
935 vlc_playlist_SetPlaybackRepeat(playlist
, VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
);
937 assert(vlc_playlist_GetPlaybackRepeat(playlist
) ==
938 VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
);
940 assert(ctx
.vec_playback_repeat_changed
.size
== 1);
941 assert(ctx
.vec_playback_repeat_changed
.data
[0].repeat
==
942 VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
);
944 callback_ctx_destroy(&ctx
);
945 vlc_playlist_RemoveListener(playlist
, listener
);
946 vlc_playlist_Delete(playlist
);
950 test_playback_order_changed_callbacks(void)
952 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
955 playlist
->order
= VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL
;
957 struct vlc_playlist_callbacks cbs
= {
958 .on_playback_order_changed
= callback_on_playback_order_changed
,
961 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
962 vlc_playlist_listener_id
*listener
=
963 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
966 vlc_playlist_SetPlaybackOrder(playlist
, VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
);
968 assert(vlc_playlist_GetPlaybackOrder(playlist
) ==
969 VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
);
971 assert(ctx
.vec_playback_order_changed
.size
== 1);
972 assert(ctx
.vec_playback_order_changed
.data
[0].order
==
973 VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
);
975 callback_ctx_destroy(&ctx
);
976 vlc_playlist_RemoveListener(playlist
, listener
);
977 vlc_playlist_Delete(playlist
);
981 test_callbacks_on_add_listener(void)
983 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
986 input_item_t
*media
[10];
987 CreateDummyMediaArray(media
, 10);
989 /* initial playlist with 10 items */
990 int ret
= vlc_playlist_Append(playlist
, media
, 10);
991 assert(ret
== VLC_SUCCESS
);
993 vlc_playlist_SetPlaybackRepeat(playlist
, VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
);
994 vlc_playlist_SetPlaybackOrder(playlist
, VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL
);
996 ret
= vlc_playlist_GoTo(playlist
, 5);
997 assert(ret
== VLC_SUCCESS
);
999 struct vlc_playlist_callbacks cbs
= {
1000 .on_items_reset
= callback_on_items_reset
,
1001 .on_playback_repeat_changed
= callback_on_playback_repeat_changed
,
1002 .on_playback_order_changed
= callback_on_playback_order_changed
,
1003 .on_current_index_changed
= callback_on_current_index_changed
,
1004 .on_has_prev_changed
= callback_on_has_prev_changed
,
1005 .on_has_next_changed
= callback_on_has_next_changed
,
1008 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1009 vlc_playlist_listener_id
*listener
=
1010 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, true);
1013 assert(ctx
.vec_items_reset
.size
== 1);
1014 assert(ctx
.vec_items_reset
.data
[0].count
== 10);
1016 assert(ctx
.vec_playback_repeat_changed
.size
== 1);
1017 assert(ctx
.vec_playback_repeat_changed
.data
[0].repeat
==
1018 VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
);
1020 assert(ctx
.vec_playback_order_changed
.size
== 1);
1021 assert(ctx
.vec_playback_order_changed
.data
[0].order
==
1022 VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL
);
1024 assert(ctx
.vec_current_index_changed
.size
== 1);
1025 assert(ctx
.vec_current_index_changed
.data
[0].current
== 5);
1027 assert(ctx
.vec_has_prev_changed
.size
== 1);
1028 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1030 assert(ctx
.vec_has_next_changed
.size
== 1);
1031 assert(ctx
.vec_has_next_changed
.data
[0].has_next
);
1033 callback_ctx_destroy(&ctx
);
1034 vlc_playlist_RemoveListener(playlist
, listener
);
1035 DestroyMediaArray(media
, 10);
1036 vlc_playlist_Delete(playlist
);
1042 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1045 input_item_t
*media
[10];
1046 CreateDummyMediaArray(media
, 10);
1048 /* initial playlist with 9 items (1 is not added) */
1049 int ret
= vlc_playlist_Append(playlist
, media
, 9);
1050 assert(ret
== VLC_SUCCESS
);
1052 assert(vlc_playlist_IndexOfMedia(playlist
, media
[4]) == 4);
1053 /* only items 0 to 8 were added */
1054 assert(vlc_playlist_IndexOfMedia(playlist
, media
[9]) == -1);
1056 vlc_playlist_item_t
*item
= vlc_playlist_Get(playlist
, 4);
1057 assert(vlc_playlist_IndexOf(playlist
, item
) == 4);
1059 vlc_playlist_item_Hold(item
);
1060 vlc_playlist_RemoveOne(playlist
, 4);
1061 assert(vlc_playlist_IndexOf(playlist
, item
) == -1);
1062 vlc_playlist_item_Release(item
);
1064 DestroyMediaArray(media
, 10);
1065 vlc_playlist_Delete(playlist
);
1071 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1074 input_item_t
*media
[4];
1075 CreateDummyMediaArray(media
, 4);
1077 /* initial playlist with 3 items */
1078 int ret
= vlc_playlist_Append(playlist
, media
, 3);
1079 assert(ret
== VLC_SUCCESS
);
1081 struct vlc_playlist_callbacks cbs
= {
1082 .on_current_index_changed
= callback_on_current_index_changed
,
1083 .on_has_prev_changed
= callback_on_has_prev_changed
,
1084 .on_has_next_changed
= callback_on_has_next_changed
,
1087 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1088 vlc_playlist_listener_id
*listener
=
1089 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1092 playlist
->current
= 2; /* last item */
1093 playlist
->has_prev
= true;
1094 playlist
->has_next
= false;
1096 /* go to the previous item (at index 1) */
1097 assert(vlc_playlist_HasPrev(playlist
));
1098 ret
= vlc_playlist_Prev(playlist
);
1099 assert(ret
== VLC_SUCCESS
);
1101 assert(playlist
->current
== 1);
1102 assert(playlist
->has_prev
);
1103 assert(playlist
->has_next
);
1105 assert(ctx
.vec_current_index_changed
.size
== 1);
1106 assert(ctx
.vec_current_index_changed
.data
[0].current
== 1);
1108 assert(ctx
.vec_has_prev_changed
.size
== 0);
1110 assert(ctx
.vec_has_next_changed
.size
== 1);
1111 assert(ctx
.vec_has_next_changed
.data
[0].has_next
);
1113 callback_ctx_reset(&ctx
);
1115 /* go to the previous item (at index 0) */
1116 assert(vlc_playlist_HasPrev(playlist
));
1117 ret
= vlc_playlist_Prev(playlist
);
1118 assert(ret
== VLC_SUCCESS
);
1120 assert(playlist
->current
== 0);
1121 assert(!playlist
->has_prev
);
1122 assert(playlist
->has_next
);
1124 assert(ctx
.vec_current_index_changed
.size
== 1);
1125 assert(ctx
.vec_current_index_changed
.data
[0].current
== 0);
1127 assert(ctx
.vec_has_prev_changed
.size
== 1);
1128 assert(!ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1130 assert(ctx
.vec_has_next_changed
.size
== 0);
1132 /* no more previous item */
1133 assert(!vlc_playlist_HasPrev(playlist
));
1135 /* returns an error, but does not crash */
1136 assert(vlc_playlist_Prev(playlist
) == VLC_EGENERIC
);
1138 callback_ctx_destroy(&ctx
);
1139 vlc_playlist_RemoveListener(playlist
, listener
);
1140 DestroyMediaArray(media
, 4);
1141 vlc_playlist_Delete(playlist
);
1147 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1150 input_item_t
*media
[3];
1151 CreateDummyMediaArray(media
, 3);
1153 /* initial playlist with 3 items */
1154 int ret
= vlc_playlist_Append(playlist
, media
, 3);
1155 assert(ret
== VLC_SUCCESS
);
1157 struct vlc_playlist_callbacks cbs
= {
1158 .on_current_index_changed
= callback_on_current_index_changed
,
1159 .on_has_prev_changed
= callback_on_has_prev_changed
,
1160 .on_has_next_changed
= callback_on_has_next_changed
,
1163 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1164 vlc_playlist_listener_id
*listener
=
1165 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1168 playlist
->current
= 0; /* first item */
1169 playlist
->has_prev
= false;
1170 playlist
->has_next
= true;
1172 /* go to the next item (at index 1) */
1173 assert(vlc_playlist_HasNext(playlist
));
1174 ret
= vlc_playlist_Next(playlist
);
1175 assert(ret
== VLC_SUCCESS
);
1177 assert(playlist
->current
== 1);
1178 assert(playlist
->has_prev
);
1179 assert(playlist
->has_next
);
1181 assert(ctx
.vec_current_index_changed
.size
== 1);
1182 assert(ctx
.vec_current_index_changed
.data
[0].current
== 1);
1184 assert(ctx
.vec_has_prev_changed
.size
== 1);
1185 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1187 assert(ctx
.vec_has_next_changed
.size
== 0);
1189 callback_ctx_reset(&ctx
);
1191 /* go to the next item (at index 2) */
1192 assert(vlc_playlist_HasNext(playlist
));
1193 ret
= vlc_playlist_Next(playlist
);
1194 assert(ret
== VLC_SUCCESS
);
1196 assert(playlist
->current
== 2);
1197 assert(playlist
->has_prev
);
1198 assert(!playlist
->has_next
);
1200 assert(ctx
.vec_current_index_changed
.size
== 1);
1201 assert(ctx
.vec_current_index_changed
.data
[0].current
== 2);
1203 assert(ctx
.vec_has_prev_changed
.size
== 0);
1205 assert(ctx
.vec_has_next_changed
.size
== 1);
1206 assert(!ctx
.vec_has_next_changed
.data
[0].has_next
);
1208 /* no more next item */
1209 assert(!vlc_playlist_HasNext(playlist
));
1211 /* returns an error, but does not crash */
1212 assert(vlc_playlist_Next(playlist
) == VLC_EGENERIC
);
1214 callback_ctx_destroy(&ctx
);
1215 vlc_playlist_RemoveListener(playlist
, listener
);
1216 DestroyMediaArray(media
, 3);
1217 vlc_playlist_Delete(playlist
);
1223 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1226 input_item_t
*media
[10];
1227 CreateDummyMediaArray(media
, 10);
1229 /* initial playlist with 10 items */
1230 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1231 assert(ret
== VLC_SUCCESS
);
1233 struct vlc_playlist_callbacks cbs
= {
1234 .on_current_index_changed
= callback_on_current_index_changed
,
1235 .on_has_prev_changed
= callback_on_has_prev_changed
,
1236 .on_has_next_changed
= callback_on_has_next_changed
,
1239 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1240 vlc_playlist_listener_id
*listener
=
1241 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1244 /* go to an item in the middle */
1245 ret
= vlc_playlist_GoTo(playlist
, 4);
1246 assert(ret
== VLC_SUCCESS
);
1248 assert(playlist
->current
== 4);
1249 assert(playlist
->has_prev
);
1250 assert(playlist
->has_next
);
1252 assert(ctx
.vec_current_index_changed
.size
== 1);
1253 assert(ctx
.vec_current_index_changed
.data
[0].current
== 4);
1255 assert(ctx
.vec_has_prev_changed
.size
== 1);
1256 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1258 assert(ctx
.vec_has_next_changed
.size
== 0);
1260 callback_ctx_reset(&ctx
);
1262 /* go to the same item */
1263 ret
= vlc_playlist_GoTo(playlist
, 4);
1264 assert(ret
== VLC_SUCCESS
);
1266 assert(playlist
->current
== 4);
1267 assert(playlist
->has_prev
);
1268 assert(playlist
->has_next
);
1270 assert(ctx
.vec_current_index_changed
.size
== 0);
1271 assert(ctx
.vec_has_prev_changed
.size
== 0);
1272 assert(ctx
.vec_has_next_changed
.size
== 0);
1274 callback_ctx_reset(&ctx
);
1276 /* go to the first item */
1277 ret
= vlc_playlist_GoTo(playlist
, 0);
1278 assert(ret
== VLC_SUCCESS
);
1280 assert(playlist
->current
== 0);
1281 assert(!playlist
->has_prev
);
1282 assert(playlist
->has_next
);
1284 assert(ctx
.vec_current_index_changed
.size
== 1);
1285 assert(ctx
.vec_current_index_changed
.data
[0].current
== 0);
1287 assert(ctx
.vec_has_prev_changed
.size
== 1);
1288 assert(!ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1290 assert(ctx
.vec_has_next_changed
.size
== 0);
1292 callback_ctx_reset(&ctx
);
1294 /* go to the last item */
1295 ret
= vlc_playlist_GoTo(playlist
, 9);
1296 assert(ret
== VLC_SUCCESS
);
1298 assert(playlist
->current
== 9);
1299 assert(playlist
->has_prev
);
1300 assert(!playlist
->has_next
);
1302 assert(ctx
.vec_current_index_changed
.size
== 1);
1303 assert(ctx
.vec_current_index_changed
.data
[0].current
== 9);
1305 assert(ctx
.vec_has_prev_changed
.size
== 1);
1306 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1308 assert(ctx
.vec_has_next_changed
.size
== 1);
1309 assert(!ctx
.vec_has_next_changed
.data
[0].has_next
);
1311 callback_ctx_reset(&ctx
);
1313 /* deselect current */
1314 ret
= vlc_playlist_GoTo(playlist
, -1);
1315 assert(ret
== VLC_SUCCESS
);
1317 assert(playlist
->current
== -1);
1318 assert(!playlist
->has_prev
);
1319 assert(playlist
->has_next
);
1321 assert(ctx
.vec_current_index_changed
.size
== 1);
1322 assert(ctx
.vec_current_index_changed
.data
[0].current
== -1);
1324 assert(ctx
.vec_has_prev_changed
.size
== 1);
1325 assert(!ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1327 assert(ctx
.vec_has_next_changed
.size
== 1);
1328 assert(ctx
.vec_has_next_changed
.data
[0].has_next
);
1330 callback_ctx_destroy(&ctx
);
1331 vlc_playlist_RemoveListener(playlist
, listener
);
1332 DestroyMediaArray(media
, 10);
1333 vlc_playlist_Delete(playlist
);
1337 test_request_insert(void)
1339 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1342 input_item_t
*media
[5];
1343 CreateDummyMediaArray(media
, 5);
1345 /* initial playlist with 3 items */
1346 int ret
= vlc_playlist_Append(playlist
, media
, 3);
1347 assert(ret
== VLC_SUCCESS
);
1349 struct vlc_playlist_callbacks cbs
= {
1350 .on_items_added
= callback_on_items_added
,
1353 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1354 vlc_playlist_listener_id
*listener
=
1355 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1358 /* insert 5 items at index 10 (out-of-bounds) */
1359 ret
= vlc_playlist_RequestInsert(playlist
, 10, &media
[3], 2);
1360 assert(ret
== VLC_SUCCESS
);
1362 assert(vlc_playlist_Count(playlist
) == 5);
1370 assert(ctx
.vec_items_added
.size
== 1);
1371 assert(ctx
.vec_items_added
.data
[0].index
== 3); /* index was changed */
1372 assert(ctx
.vec_items_added
.data
[0].count
== 2);
1373 assert(ctx
.vec_items_added
.data
[0].state
.playlist_size
== 5);
1375 callback_ctx_destroy(&ctx
);
1376 vlc_playlist_RemoveListener(playlist
, listener
);
1377 DestroyMediaArray(media
, 5);
1378 vlc_playlist_Delete(playlist
);
1382 test_request_remove_with_matching_hint(void)
1384 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1387 input_item_t
*media
[10];
1388 CreateDummyMediaArray(media
, 10);
1390 /* initial playlist with 10 items */
1391 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1392 assert(ret
== VLC_SUCCESS
);
1394 struct vlc_playlist_callbacks cbs
= {
1395 .on_items_removed
= callback_on_items_removed
,
1398 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1399 vlc_playlist_listener_id
*listener
=
1400 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1403 vlc_playlist_item_t
*items_to_remove
[] = {
1404 vlc_playlist_Get(playlist
, 3),
1405 vlc_playlist_Get(playlist
, 4),
1406 vlc_playlist_Get(playlist
, 5),
1407 vlc_playlist_Get(playlist
, 6),
1410 ret
= vlc_playlist_RequestRemove(playlist
, items_to_remove
, 4, 3);
1411 assert(ret
== VLC_SUCCESS
);
1413 assert(vlc_playlist_Count(playlist
) == 6);
1422 assert(ctx
.vec_items_removed
.size
== 1);
1423 assert(ctx
.vec_items_removed
.data
[0].index
== 3);
1424 assert(ctx
.vec_items_removed
.data
[0].count
== 4);
1425 assert(ctx
.vec_items_removed
.data
[0].state
.playlist_size
== 6);
1427 callback_ctx_destroy(&ctx
);
1428 vlc_playlist_RemoveListener(playlist
, listener
);
1429 DestroyMediaArray(media
, 10);
1430 vlc_playlist_Delete(playlist
);
1434 test_request_remove_without_hint(void)
1436 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1439 input_item_t
*media
[10];
1440 CreateDummyMediaArray(media
, 10);
1442 /* initial playlist with 10 items */
1443 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1444 assert(ret
== VLC_SUCCESS
);
1446 struct vlc_playlist_callbacks cbs
= {
1447 .on_items_removed
= callback_on_items_removed
,
1450 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1451 vlc_playlist_listener_id
*listener
=
1452 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1455 vlc_playlist_item_t
*items_to_remove
[] = {
1456 vlc_playlist_Get(playlist
, 3),
1457 vlc_playlist_Get(playlist
, 4),
1458 vlc_playlist_Get(playlist
, 5),
1459 vlc_playlist_Get(playlist
, 6),
1462 ret
= vlc_playlist_RequestRemove(playlist
, items_to_remove
, 4, -1);
1463 assert(ret
== VLC_SUCCESS
);
1465 assert(vlc_playlist_Count(playlist
) == 6);
1474 assert(ctx
.vec_items_removed
.size
== 1);
1475 assert(ctx
.vec_items_removed
.data
[0].index
== 3);
1476 assert(ctx
.vec_items_removed
.data
[0].count
== 4);
1477 assert(ctx
.vec_items_removed
.data
[0].state
.playlist_size
== 6);
1479 callback_ctx_destroy(&ctx
);
1480 vlc_playlist_RemoveListener(playlist
, listener
);
1481 DestroyMediaArray(media
, 10);
1482 vlc_playlist_Delete(playlist
);
1486 test_request_remove_adapt(void)
1488 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1491 input_item_t
*media
[11];
1492 CreateDummyMediaArray(media
, 11);
1494 /* initial playlist with 10 items */
1495 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1496 assert(ret
== VLC_SUCCESS
);
1498 struct vlc_playlist_callbacks cbs
= {
1499 .on_items_removed
= callback_on_items_removed
,
1502 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1503 vlc_playlist_listener_id
*listener
=
1504 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1507 vlc_playlist_item_t
*dummy
= vlc_playlist_item_New(media
[10], 0);
1510 /* remove items in a wrong order at wrong position, as if the playlist had
1511 * been sorted/shuffled before the request were applied */
1512 vlc_playlist_item_t
*items_to_remove
[] = {
1513 vlc_playlist_Get(playlist
, 3),
1514 vlc_playlist_Get(playlist
, 2),
1515 vlc_playlist_Get(playlist
, 6),
1516 vlc_playlist_Get(playlist
, 9),
1517 vlc_playlist_Get(playlist
, 1),
1518 dummy
, /* inexistant */
1519 vlc_playlist_Get(playlist
, 8),
1522 ret
= vlc_playlist_RequestRemove(playlist
, items_to_remove
, 7, 3);
1523 assert(ret
== VLC_SUCCESS
);
1525 vlc_playlist_item_Release(dummy
);
1527 assert(vlc_playlist_Count(playlist
) == 4);
1534 /* it should notify 3 different slices removed, in descending order for
1535 * optimization: {8,9}, {6}, {1,2,3}. */
1537 assert(ctx
.vec_items_removed
.size
== 3);
1539 assert(ctx
.vec_items_removed
.data
[0].index
== 8);
1540 assert(ctx
.vec_items_removed
.data
[0].count
== 2);
1541 assert(ctx
.vec_items_removed
.data
[0].state
.playlist_size
== 8);
1543 assert(ctx
.vec_items_removed
.data
[1].index
== 6);
1544 assert(ctx
.vec_items_removed
.data
[1].count
== 1);
1545 assert(ctx
.vec_items_removed
.data
[1].state
.playlist_size
== 7);
1547 assert(ctx
.vec_items_removed
.data
[2].index
== 1);
1548 assert(ctx
.vec_items_removed
.data
[2].count
== 3);
1549 assert(ctx
.vec_items_removed
.data
[2].state
.playlist_size
== 4);
1551 callback_ctx_destroy(&ctx
);
1552 vlc_playlist_RemoveListener(playlist
, listener
);
1553 DestroyMediaArray(media
, 11);
1554 vlc_playlist_Delete(playlist
);
1558 test_request_move_with_matching_hint(void)
1560 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1563 input_item_t
*media
[10];
1564 CreateDummyMediaArray(media
, 10);
1566 /* initial playlist with 10 items */
1567 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1568 assert(ret
== VLC_SUCCESS
);
1570 struct vlc_playlist_callbacks cbs
= {
1571 .on_items_moved
= callback_on_items_moved
,
1574 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1575 vlc_playlist_listener_id
*listener
=
1576 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1579 vlc_playlist_item_t
*items_to_move
[] = {
1580 vlc_playlist_Get(playlist
, 5),
1581 vlc_playlist_Get(playlist
, 6),
1582 vlc_playlist_Get(playlist
, 7),
1583 vlc_playlist_Get(playlist
, 8),
1586 ret
= vlc_playlist_RequestMove(playlist
, items_to_move
, 4, 2, 5);
1587 assert(ret
== VLC_SUCCESS
);
1589 assert(vlc_playlist_Count(playlist
) == 10);
1602 assert(ctx
.vec_items_moved
.size
== 1);
1603 assert(ctx
.vec_items_moved
.data
[0].index
== 5);
1604 assert(ctx
.vec_items_moved
.data
[0].count
== 4);
1605 assert(ctx
.vec_items_moved
.data
[0].state
.playlist_size
== 10);
1607 callback_ctx_destroy(&ctx
);
1608 vlc_playlist_RemoveListener(playlist
, listener
);
1609 DestroyMediaArray(media
, 10);
1610 vlc_playlist_Delete(playlist
);
1614 test_request_move_without_hint(void)
1616 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1619 input_item_t
*media
[10];
1620 CreateDummyMediaArray(media
, 10);
1622 /* initial playlist with 10 items */
1623 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1624 assert(ret
== VLC_SUCCESS
);
1626 struct vlc_playlist_callbacks cbs
= {
1627 .on_items_moved
= callback_on_items_moved
,
1630 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1631 vlc_playlist_listener_id
*listener
=
1632 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1635 vlc_playlist_item_t
*items_to_move
[] = {
1636 vlc_playlist_Get(playlist
, 5),
1637 vlc_playlist_Get(playlist
, 6),
1638 vlc_playlist_Get(playlist
, 7),
1639 vlc_playlist_Get(playlist
, 8),
1642 ret
= vlc_playlist_RequestMove(playlist
, items_to_move
, 4, 2, -1);
1643 assert(ret
== VLC_SUCCESS
);
1645 assert(vlc_playlist_Count(playlist
) == 10);
1658 assert(ctx
.vec_items_moved
.size
== 1);
1659 assert(ctx
.vec_items_moved
.data
[0].index
== 5);
1660 assert(ctx
.vec_items_moved
.data
[0].count
== 4);
1661 assert(ctx
.vec_items_moved
.data
[0].state
.playlist_size
== 10);
1663 vlc_playlist_item_t
*item
= vlc_playlist_Get(playlist
, 3);
1664 /* move it to index 42 (out of bounds) */
1665 vlc_playlist_RequestMove(playlist
, &item
, 1, 42, -1);
1678 callback_ctx_destroy(&ctx
);
1679 vlc_playlist_RemoveListener(playlist
, listener
);
1680 DestroyMediaArray(media
, 10);
1681 vlc_playlist_Delete(playlist
);
1685 test_request_move_adapt(void)
1687 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1690 input_item_t
*media
[16];
1691 CreateDummyMediaArray(media
, 16);
1693 /* initial playlist with 15 items */
1694 int ret
= vlc_playlist_Append(playlist
, media
, 15);
1695 assert(ret
== VLC_SUCCESS
);
1697 struct vlc_playlist_callbacks cbs
= {
1698 .on_items_moved
= callback_on_items_moved
,
1701 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1702 vlc_playlist_listener_id
*listener
=
1703 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1706 vlc_playlist_item_t
*dummy
= vlc_playlist_item_New(media
[15], 0);
1709 /* move items in a wrong order at wrong position, as if the playlist had
1710 * been sorted/shuffled before the request were applied */
1711 vlc_playlist_item_t
*items_to_move
[] = {
1712 vlc_playlist_Get(playlist
, 7),
1713 vlc_playlist_Get(playlist
, 8),
1714 vlc_playlist_Get(playlist
, 5),
1715 vlc_playlist_Get(playlist
, 12),
1716 dummy
, /* inexistant */
1717 vlc_playlist_Get(playlist
, 3),
1718 vlc_playlist_Get(playlist
, 13),
1719 vlc_playlist_Get(playlist
, 14),
1720 vlc_playlist_Get(playlist
, 1),
1723 vlc_playlist_RequestMove(playlist
, items_to_move
, 9, 3, 2);
1725 vlc_playlist_item_Release(dummy
);
1727 assert(vlc_playlist_Count(playlist
) == 15);
1747 /* there are 6 slices to move: 7-8, 5, 12, 3, 13-14, 1 */
1748 assert(ctx
.vec_items_moved
.size
== 6);
1750 struct VLC_VECTOR(int) vec
= VLC_VECTOR_INITIALIZER
;
1751 for (int i
= 0; i
< 15; ++i
)
1752 vlc_vector_push(&vec
, i
* 10);
1754 struct items_moved_report report
;
1755 vlc_vector_foreach(report
, &ctx
.vec_items_moved
)
1756 /* apply the changes as reported by the callbacks */
1757 vlc_vector_move_slice(&vec
, report
.index
, report
.count
, report
.target
);
1759 /* the vector items must have been moved the same way as the playlist */
1760 assert(vec
.size
== 15);
1761 assert(vec
.data
[0] == 0);
1762 assert(vec
.data
[1] == 20);
1763 assert(vec
.data
[2] == 40);
1764 assert(vec
.data
[3] == 70);
1765 assert(vec
.data
[4] == 80);
1766 assert(vec
.data
[5] == 50);
1767 assert(vec
.data
[6] == 120);
1768 assert(vec
.data
[7] == 30);
1769 assert(vec
.data
[8] == 130);
1770 assert(vec
.data
[9] == 140);
1771 assert(vec
.data
[10] == 10);
1772 assert(vec
.data
[11] == 60);
1773 assert(vec
.data
[12] == 90);
1774 assert(vec
.data
[13] == 100);
1775 assert(vec
.data
[14] == 110);
1777 vlc_vector_destroy(&vec
);
1779 callback_ctx_destroy(&ctx
);
1780 vlc_playlist_RemoveListener(playlist
, listener
);
1781 DestroyMediaArray(media
, 16);
1782 vlc_playlist_Delete(playlist
);
1786 test_request_move_to_end_adapt(void)
1788 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1791 input_item_t
*media
[16];
1792 CreateDummyMediaArray(media
, 16);
1794 /* initial playlist with 15 items */
1795 int ret
= vlc_playlist_Append(playlist
, media
, 15);
1796 assert(ret
== VLC_SUCCESS
);
1798 struct vlc_playlist_callbacks cbs
= {
1799 .on_items_moved
= callback_on_items_moved
,
1802 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1803 vlc_playlist_listener_id
*listener
=
1804 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1807 vlc_playlist_item_t
*dummy
= vlc_playlist_item_New(media
[15], 0);
1810 /* move items in a wrong order at wrong position, as if the playlist had
1811 * been sorted/shuffled before the request were applied */
1812 vlc_playlist_item_t
*items_to_move
[] = {
1813 vlc_playlist_Get(playlist
, 7),
1814 vlc_playlist_Get(playlist
, 8),
1815 vlc_playlist_Get(playlist
, 5),
1816 vlc_playlist_Get(playlist
, 12),
1817 dummy
, /* inexistant */
1818 vlc_playlist_Get(playlist
, 3),
1819 vlc_playlist_Get(playlist
, 13),
1820 vlc_playlist_Get(playlist
, 14),
1821 vlc_playlist_Get(playlist
, 1),
1824 /* target 20 is far beyond the end of the list */
1825 vlc_playlist_RequestMove(playlist
, items_to_move
, 9, 20, 2);
1827 vlc_playlist_item_Release(dummy
);
1829 assert(vlc_playlist_Count(playlist
) == 15);
1848 /* there are 6 slices to move: 7-8, 5, 12, 3, 13-14, 1 */
1849 assert(ctx
.vec_items_moved
.size
== 6);
1851 struct VLC_VECTOR(int) vec
= VLC_VECTOR_INITIALIZER
;
1852 for (int i
= 0; i
< 15; ++i
)
1853 vlc_vector_push(&vec
, i
* 10);
1855 struct items_moved_report report
;
1856 vlc_vector_foreach(report
, &ctx
.vec_items_moved
)
1857 /* apply the changes as reported by the callbacks */
1858 vlc_vector_move_slice(&vec
, report
.index
, report
.count
, report
.target
);
1860 /* the vector items must have been moved the same way as the playlist */
1861 assert(vec
.size
== 15);
1862 assert(vec
.data
[0] == 0);
1863 assert(vec
.data
[1] == 20);
1864 assert(vec
.data
[2] == 40);
1865 assert(vec
.data
[3] == 60);
1866 assert(vec
.data
[4] == 90);
1867 assert(vec
.data
[5] == 100);
1868 assert(vec
.data
[6] == 110);
1869 assert(vec
.data
[7] == 70);
1870 assert(vec
.data
[8] == 80);
1871 assert(vec
.data
[9] == 50);
1872 assert(vec
.data
[10] == 120);
1873 assert(vec
.data
[11] == 30);
1874 assert(vec
.data
[12] == 130);
1875 assert(vec
.data
[13] == 140);
1876 assert(vec
.data
[14] == 10);
1878 vlc_vector_destroy(&vec
);
1880 callback_ctx_destroy(&ctx
);
1881 vlc_playlist_RemoveListener(playlist
, listener
);
1882 DestroyMediaArray(media
, 16);
1883 vlc_playlist_Delete(playlist
);
1887 test_request_goto_with_matching_hint(void)
1889 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1892 input_item_t
*media
[10];
1893 CreateDummyMediaArray(media
, 10);
1895 /* initial playlist with 10 items */
1896 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1897 assert(ret
== VLC_SUCCESS
);
1899 struct vlc_playlist_callbacks cbs
= {
1900 .on_current_index_changed
= callback_on_current_index_changed
,
1901 .on_has_prev_changed
= callback_on_has_prev_changed
,
1902 .on_has_next_changed
= callback_on_has_next_changed
,
1905 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1906 vlc_playlist_listener_id
*listener
=
1907 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1910 /* go to an item in the middle, with incorrect index_hint */
1911 vlc_playlist_item_t
*item
= vlc_playlist_Get(playlist
, 4);
1912 ret
= vlc_playlist_RequestGoTo(playlist
, item
, 4);
1913 assert(ret
== VLC_SUCCESS
);
1915 assert(playlist
->current
== 4);
1916 assert(playlist
->has_prev
);
1917 assert(playlist
->has_next
);
1919 assert(ctx
.vec_current_index_changed
.size
== 1);
1920 assert(ctx
.vec_current_index_changed
.data
[0].current
== 4);
1922 assert(ctx
.vec_has_prev_changed
.size
== 1);
1923 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1925 assert(ctx
.vec_has_next_changed
.size
== 0);
1927 callback_ctx_destroy(&ctx
);
1928 vlc_playlist_RemoveListener(playlist
, listener
);
1929 DestroyMediaArray(media
, 10);
1930 vlc_playlist_Delete(playlist
);
1934 test_request_goto_without_hint(void)
1936 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1939 input_item_t
*media
[10];
1940 CreateDummyMediaArray(media
, 10);
1942 /* initial playlist with 10 items */
1943 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1944 assert(ret
== VLC_SUCCESS
);
1946 struct vlc_playlist_callbacks cbs
= {
1947 .on_current_index_changed
= callback_on_current_index_changed
,
1948 .on_has_prev_changed
= callback_on_has_prev_changed
,
1949 .on_has_next_changed
= callback_on_has_next_changed
,
1952 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
1953 vlc_playlist_listener_id
*listener
=
1954 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
1957 /* go to an item in the middle, with incorrect index_hint */
1958 vlc_playlist_item_t
*item
= vlc_playlist_Get(playlist
, 4);
1959 ret
= vlc_playlist_RequestGoTo(playlist
, item
, -1); /* no hint */
1960 assert(ret
== VLC_SUCCESS
);
1962 assert(playlist
->current
== 4);
1963 assert(playlist
->has_prev
);
1964 assert(playlist
->has_next
);
1966 assert(ctx
.vec_current_index_changed
.size
== 1);
1967 assert(ctx
.vec_current_index_changed
.data
[0].current
== 4);
1969 assert(ctx
.vec_has_prev_changed
.size
== 1);
1970 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
1972 assert(ctx
.vec_has_next_changed
.size
== 0);
1974 callback_ctx_destroy(&ctx
);
1975 vlc_playlist_RemoveListener(playlist
, listener
);
1976 DestroyMediaArray(media
, 10);
1977 vlc_playlist_Delete(playlist
);
1981 test_request_goto_adapt(void)
1983 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
1986 input_item_t
*media
[10];
1987 CreateDummyMediaArray(media
, 10);
1989 /* initial playlist with 10 items */
1990 int ret
= vlc_playlist_Append(playlist
, media
, 10);
1991 assert(ret
== VLC_SUCCESS
);
1993 struct vlc_playlist_callbacks cbs
= {
1994 .on_current_index_changed
= callback_on_current_index_changed
,
1995 .on_has_prev_changed
= callback_on_has_prev_changed
,
1996 .on_has_next_changed
= callback_on_has_next_changed
,
1999 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
2000 vlc_playlist_listener_id
*listener
=
2001 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
2004 /* go to an item in the middle, with incorrect index_hint */
2005 vlc_playlist_item_t
*item
= vlc_playlist_Get(playlist
, 4);
2006 ret
= vlc_playlist_RequestGoTo(playlist
, item
, 7); /* wrong index hint */
2007 assert(ret
== VLC_SUCCESS
);
2009 assert(playlist
->current
== 4);
2010 assert(playlist
->has_prev
);
2011 assert(playlist
->has_next
);
2013 assert(ctx
.vec_current_index_changed
.size
== 1);
2014 assert(ctx
.vec_current_index_changed
.data
[0].current
== 4);
2016 assert(ctx
.vec_has_prev_changed
.size
== 1);
2017 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
2019 assert(ctx
.vec_has_next_changed
.size
== 0);
2021 callback_ctx_destroy(&ctx
);
2022 vlc_playlist_RemoveListener(playlist
, listener
);
2023 DestroyMediaArray(media
, 10);
2024 vlc_playlist_Delete(playlist
);
2027 /* this only tests that the randomizer is correctly managed by the playlist,
2028 * for further tests on randomization properties, see randomizer tests. */
2032 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
2035 input_item_t
*media
[6];
2036 CreateDummyMediaArray(media
, 6);
2038 /* initial playlist with 5 items (1 is not added immediately) */
2039 int ret
= vlc_playlist_Append(playlist
, media
, 5);
2040 assert(ret
== VLC_SUCCESS
);
2042 struct vlc_playlist_callbacks cbs
= {
2043 .on_current_index_changed
= callback_on_current_index_changed
,
2044 .on_has_prev_changed
= callback_on_has_prev_changed
,
2045 .on_has_next_changed
= callback_on_has_next_changed
,
2048 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
2049 vlc_playlist_listener_id
*listener
=
2050 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
2053 assert(!vlc_playlist_HasPrev(playlist
));
2054 assert(vlc_playlist_HasNext(playlist
));
2056 for (int i
= 0; i
< 3; ++i
)
2058 assert(vlc_playlist_HasNext(playlist
));
2059 ret
= vlc_playlist_Next(playlist
);
2060 assert(ret
== VLC_SUCCESS
);
2063 assert(vlc_playlist_HasPrev(playlist
));
2064 vlc_playlist_SetPlaybackOrder(playlist
, VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
);
2066 /* in random order, previous uses the history of randomly selected items */
2067 assert(!vlc_playlist_HasPrev(playlist
));
2069 bool selected
[5] = {};
2070 for (int i
= 0; i
< 5; ++i
)
2072 assert(vlc_playlist_HasNext(playlist
));
2073 ret
= vlc_playlist_Next(playlist
);
2074 assert(ret
== VLC_SUCCESS
);
2075 ssize_t index
= vlc_playlist_GetCurrentIndex(playlist
);
2076 assert(index
!= -1);
2077 assert(!selected
[index
]); /* not selected twice */
2078 selected
[index
] = true;
2081 assert(!vlc_playlist_HasNext(playlist
));
2083 /* add a new item, it must be taken into account */
2084 ret
= vlc_playlist_AppendOne(playlist
, media
[5]);
2085 assert(ret
== VLC_SUCCESS
);
2086 assert(vlc_playlist_HasNext(playlist
));
2088 ret
= vlc_playlist_Next(playlist
);
2089 assert(ret
== VLC_SUCCESS
);
2091 assert(vlc_playlist_GetCurrentIndex(playlist
) == 5);
2092 assert(!vlc_playlist_HasNext(playlist
));
2094 vlc_playlist_RemoveOne(playlist
, 5);
2097 vlc_playlist_SetPlaybackRepeat(playlist
, VLC_PLAYLIST_PLAYBACK_REPEAT_ALL
);
2099 /* now there are more items */
2100 assert(vlc_playlist_HasNext(playlist
));
2103 memset(selected
, 0, sizeof(selected
));
2104 for (int i
= 0; i
< 5; ++i
)
2106 assert(vlc_playlist_HasNext(playlist
));
2107 ret
= vlc_playlist_Next(playlist
);
2108 assert(ret
== VLC_SUCCESS
);
2109 ssize_t index
= vlc_playlist_GetCurrentIndex(playlist
);
2110 assert(index
!= -1);
2111 assert(!selected
[index
]); /* not selected twice */
2112 selected
[index
] = true;
2115 /* there are always more items */
2116 assert(vlc_playlist_HasNext(playlist
));
2118 /* move to the middle of the random array */
2119 for (int i
= 0; i
< 3; ++i
)
2121 assert(vlc_playlist_HasNext(playlist
));
2122 ret
= vlc_playlist_Next(playlist
);
2123 assert(ret
== VLC_SUCCESS
);
2126 memset(selected
, 0, sizeof(selected
));
2127 int actual
[5]; /* store the selected items (by their index) */
2129 ssize_t current
= vlc_playlist_GetCurrentIndex(playlist
);
2130 assert(current
!= -1);
2131 actual
[4] = current
;
2133 for (int i
= 3; i
>= 0; --i
)
2135 assert(vlc_playlist_HasPrev(playlist
));
2136 ret
= vlc_playlist_Prev(playlist
);
2137 assert(ret
== VLC_SUCCESS
);
2138 ssize_t index
= vlc_playlist_GetCurrentIndex(playlist
);
2139 assert(index
!= -1);
2141 assert(!selected
[index
]); /* not selected twice */
2142 selected
[index
] = true;
2145 /* no more previous, the history may only contain each item once */
2146 assert(!vlc_playlist_HasPrev(playlist
));
2148 /* we should get the same items in the reverse order going forward */
2149 for (int i
= 1; i
< 5; ++i
)
2151 assert(vlc_playlist_HasNext(playlist
));
2152 ret
= vlc_playlist_Next(playlist
);
2153 assert(ret
== VLC_SUCCESS
);
2154 ssize_t index
= vlc_playlist_GetCurrentIndex(playlist
);
2155 assert(index
!= -1);
2156 assert(index
== actual
[i
]);
2159 /* there are always more items */
2160 assert(vlc_playlist_HasNext(playlist
));
2162 callback_ctx_destroy(&ctx
);
2163 vlc_playlist_RemoveListener(playlist
, listener
);
2164 DestroyMediaArray(media
, 6);
2165 vlc_playlist_Delete(playlist
);
2171 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
2174 input_item_t
*media
[10];
2175 CreateDummyMediaArray(media
, 10);
2177 /* initial playlist with 10 items */
2178 int ret
= vlc_playlist_Append(playlist
, media
, 10);
2179 assert(ret
== VLC_SUCCESS
);
2181 struct vlc_playlist_callbacks cbs
= {
2182 .on_items_reset
= callback_on_items_reset
,
2183 .on_current_index_changed
= callback_on_current_index_changed
,
2184 .on_has_prev_changed
= callback_on_has_prev_changed
,
2185 .on_has_next_changed
= callback_on_has_next_changed
,
2188 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
2189 vlc_playlist_listener_id
*listener
=
2190 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
2193 playlist
->current
= 4;
2194 playlist
->has_prev
= true;
2195 playlist
->has_next
= true;
2197 vlc_playlist_Shuffle(playlist
);
2199 ssize_t index
= vlc_playlist_IndexOfMedia(playlist
, media
[4]);
2200 assert(index
!= -1);
2201 assert(index
== playlist
->current
);
2203 assert(ctx
.vec_items_reset
.size
== 1);
2204 assert(ctx
.vec_items_reset
.data
[0].count
== 10);
2205 assert(ctx
.vec_items_reset
.data
[0].state
.playlist_size
== 10);
2206 assert(ctx
.vec_items_reset
.data
[0].state
.current
== index
);
2207 assert(ctx
.vec_items_reset
.data
[0].state
.has_prev
== (index
> 0));
2208 assert(ctx
.vec_items_reset
.data
[0].state
.has_next
== (index
< 9));
2211 assert(ctx
.vec_current_index_changed
.size
== 0);
2214 assert(ctx
.vec_current_index_changed
.size
== 1);
2215 assert(ctx
.vec_current_index_changed
.data
[0].current
== index
);
2220 assert(!playlist
->has_prev
);
2221 assert(ctx
.vec_has_prev_changed
.size
== 1);
2222 assert(!ctx
.vec_has_prev_changed
.data
[0].has_prev
);
2226 assert(playlist
->has_prev
);
2227 assert(ctx
.vec_has_prev_changed
.size
== 0);
2232 assert(!playlist
->has_next
);
2233 assert(ctx
.vec_has_next_changed
.size
== 1);
2234 assert(!ctx
.vec_has_next_changed
.data
[0].has_next
);
2238 assert(playlist
->has_next
);
2239 assert(ctx
.vec_has_next_changed
.size
== 0);
2242 callback_ctx_destroy(&ctx
);
2243 vlc_playlist_RemoveListener(playlist
, listener
);
2244 DestroyMediaArray(media
, 10);
2245 vlc_playlist_Delete(playlist
);
2251 vlc_playlist_t
*playlist
= vlc_playlist_New(NULL
);
2254 input_item_t
*media
[10];
2255 media
[0] = CreateDummyMedia(4); media
[0]->i_duration
= 42;
2256 media
[1] = CreateDummyMedia(1); media
[1]->i_duration
= 5;
2257 media
[2] = CreateDummyMedia(6); media
[2]->i_duration
= 100;
2258 media
[3] = CreateDummyMedia(2); media
[3]->i_duration
= 1;
2259 media
[4] = CreateDummyMedia(1); media
[4]->i_duration
= 8;
2260 media
[5] = CreateDummyMedia(4); media
[5]->i_duration
= 23;
2261 media
[6] = CreateDummyMedia(3); media
[6]->i_duration
= 60;
2262 media
[7] = CreateDummyMedia(3); media
[7]->i_duration
= 40;
2263 media
[8] = CreateDummyMedia(0); media
[8]->i_duration
= 42;
2264 media
[9] = CreateDummyMedia(5); media
[9]->i_duration
= 42;
2266 /* initial playlist with 10 items */
2267 int ret
= vlc_playlist_Append(playlist
, media
, 10);
2268 assert(ret
== VLC_SUCCESS
);
2270 struct vlc_playlist_callbacks cbs
= {
2271 .on_items_reset
= callback_on_items_reset
,
2272 .on_current_index_changed
= callback_on_current_index_changed
,
2273 .on_has_prev_changed
= callback_on_has_prev_changed
,
2274 .on_has_next_changed
= callback_on_has_next_changed
,
2277 struct callback_ctx ctx
= CALLBACK_CTX_INITIALIZER
;
2278 vlc_playlist_listener_id
*listener
=
2279 vlc_playlist_AddListener(playlist
, &cbs
, &ctx
, false);
2282 playlist
->current
= 0;
2283 playlist
->has_prev
= false;
2284 playlist
->has_next
= true;
2286 struct vlc_playlist_sort_criterion criteria1
[] = {
2287 { VLC_PLAYLIST_SORT_KEY_TITLE
, VLC_PLAYLIST_SORT_ORDER_ASCENDING
},
2288 { VLC_PLAYLIST_SORT_KEY_DURATION
, VLC_PLAYLIST_SORT_ORDER_ASCENDING
},
2290 vlc_playlist_Sort(playlist
, criteria1
, 2);
2303 ssize_t index
= vlc_playlist_IndexOfMedia(playlist
, media
[0]);
2305 assert(playlist
->current
== 7);
2307 assert(ctx
.vec_items_reset
.size
== 1);
2308 assert(ctx
.vec_items_reset
.data
[0].count
== 10);
2309 assert(ctx
.vec_items_reset
.data
[0].state
.playlist_size
== 10);
2310 assert(ctx
.vec_items_reset
.data
[0].state
.current
== 7);
2311 assert(ctx
.vec_items_reset
.data
[0].state
.has_prev
);
2312 assert(ctx
.vec_items_reset
.data
[0].state
.has_next
);
2314 assert(ctx
.vec_current_index_changed
.size
== 1);
2315 assert(ctx
.vec_current_index_changed
.data
[0].current
== 7);
2317 assert(ctx
.vec_has_prev_changed
.size
== 1);
2318 assert(ctx
.vec_has_prev_changed
.data
[0].has_prev
);
2320 assert(ctx
.vec_has_next_changed
.size
== 0);
2322 callback_ctx_reset(&ctx
);
2324 struct vlc_playlist_sort_criterion criteria2
[] = {
2325 { VLC_PLAYLIST_SORT_KEY_DURATION
, VLC_PLAYLIST_SORT_ORDER_DESCENDING
},
2326 { VLC_PLAYLIST_SORT_KEY_TITLE
, VLC_PLAYLIST_SORT_ORDER_ASCENDING
},
2329 vlc_playlist_Sort(playlist
, criteria2
, 2);
2342 assert(ctx
.vec_items_reset
.size
== 1);
2343 assert(ctx
.vec_items_reset
.data
[0].count
== 10);
2344 assert(ctx
.vec_items_reset
.data
[0].state
.playlist_size
== 10);
2346 callback_ctx_destroy(&ctx
);
2347 vlc_playlist_RemoveListener(playlist
, listener
);
2348 DestroyMediaArray(media
, 10);
2349 vlc_playlist_Delete(playlist
);
2362 test_items_added_callbacks();
2363 test_items_moved_callbacks();
2364 test_items_removed_callbacks();
2365 test_items_reset_callbacks();
2366 test_playback_repeat_changed_callbacks();
2367 test_playback_order_changed_callbacks();
2368 test_callbacks_on_add_listener();
2373 test_request_insert();
2374 test_request_remove_with_matching_hint();
2375 test_request_remove_without_hint();
2376 test_request_remove_adapt();
2377 test_request_move_with_matching_hint();
2378 test_request_move_without_hint();
2379 test_request_move_adapt();
2380 test_request_move_to_end_adapt();
2381 test_request_goto_with_matching_hint();
2382 test_request_goto_without_hint();
2383 test_request_goto_adapt();