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_ClearItems(vlc_playlist_t
*playlist
)
35 vlc_playlist_item_t
*item
;
36 vlc_vector_foreach(item
, &playlist
->items
)
37 vlc_playlist_item_Release(item
);
38 vlc_vector_clear(&playlist
->items
);
42 vlc_playlist_ItemsReset(vlc_playlist_t
*playlist
)
44 if (playlist
->order
== VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
)
45 randomizer_Clear(&playlist
->randomizer
);
47 struct vlc_playlist_state state
;
48 vlc_playlist_state_Save(playlist
, &state
);
50 playlist
->current
= -1;
51 playlist
->has_prev
= vlc_playlist_ComputeHasPrev(playlist
);
52 playlist
->has_next
= vlc_playlist_ComputeHasNext(playlist
);
54 vlc_playlist_Notify(playlist
, on_items_reset
, playlist
->items
.data
,
55 playlist
->items
.size
);
56 vlc_playlist_state_NotifyChanges(playlist
, &state
);
60 vlc_playlist_ItemsInserted(vlc_playlist_t
*playlist
, size_t index
, size_t count
)
62 if (playlist
->order
== VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
)
63 randomizer_Add(&playlist
->randomizer
,
64 &playlist
->items
.data
[index
], count
);
66 struct vlc_playlist_state state
;
67 vlc_playlist_state_Save(playlist
, &state
);
69 if (playlist
->current
>= (ssize_t
) index
)
70 playlist
->current
+= count
;
71 playlist
->has_prev
= vlc_playlist_ComputeHasPrev(playlist
);
72 playlist
->has_next
= vlc_playlist_ComputeHasNext(playlist
);
74 vlc_playlist_item_t
**items
= &playlist
->items
.data
[index
];
75 vlc_playlist_Notify(playlist
, on_items_added
, index
, items
, count
);
76 vlc_playlist_state_NotifyChanges(playlist
, &state
);
80 vlc_playlist_ItemsMoved(vlc_playlist_t
*playlist
, size_t index
, size_t count
,
83 struct vlc_playlist_state state
;
84 vlc_playlist_state_Save(playlist
, &state
);
86 if (playlist
->current
!= -1) {
87 size_t current
= (size_t) playlist
->current
;
90 if (current
>= index
&& current
< index
+ count
)
91 /* current item belongs to the moved block */
92 playlist
->current
+= target
- index
;
93 else if (current
>= index
+ count
&& current
< target
+ count
)
94 /* current item was shifted backwards to the moved block */
95 playlist
->current
-= count
;
96 /* else the current item does not move */
100 if (current
>= index
&& current
< index
+ count
)
101 /* current item belongs to the moved block */
102 playlist
->current
-= index
- target
;
103 else if (current
>= target
&& current
< index
)
104 /* current item was shifted forward to the moved block */
105 playlist
->current
+= count
;
106 /* else the current item does not move */
110 playlist
->has_prev
= vlc_playlist_ComputeHasPrev(playlist
);
111 playlist
->has_next
= vlc_playlist_ComputeHasNext(playlist
);
113 vlc_playlist_Notify(playlist
, on_items_moved
, index
, count
, target
);
114 vlc_playlist_state_NotifyChanges(playlist
, &state
);
118 vlc_playlist_ItemsRemoving(vlc_playlist_t
*playlist
, size_t index
, size_t count
)
120 if (playlist
->order
== VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM
)
121 randomizer_Remove(&playlist
->randomizer
,
122 &playlist
->items
.data
[index
], count
);
125 /* return whether the current media has changed */
127 vlc_playlist_ItemsRemoved(vlc_playlist_t
*playlist
, size_t index
, size_t count
)
129 struct vlc_playlist_state state
;
130 vlc_playlist_state_Save(playlist
, &state
);
132 bool current_media_changed
= false;
133 if (playlist
->current
!= -1) {
134 size_t current
= (size_t) playlist
->current
;
135 if (current
>= index
&& current
< index
+ count
) {
136 /* current item has been removed */
137 if (index
+ count
< playlist
->items
.size
) {
138 /* select the first item after the removed block */
139 playlist
->current
= index
;
142 playlist
->current
= -1;
144 current_media_changed
= true;
145 } else if (current
>= index
+ count
) {
146 playlist
->current
-= count
;
149 playlist
->has_prev
= vlc_playlist_ComputeHasPrev(playlist
);
150 playlist
->has_next
= vlc_playlist_ComputeHasNext(playlist
);
152 vlc_playlist_Notify(playlist
, on_items_removed
, index
, count
);
153 vlc_playlist_state_NotifyChanges(playlist
, &state
);
155 return current_media_changed
;
159 vlc_playlist_Count(vlc_playlist_t
*playlist
)
161 vlc_playlist_AssertLocked(playlist
);
162 return playlist
->items
.size
;
165 vlc_playlist_item_t
*
166 vlc_playlist_Get(vlc_playlist_t
*playlist
, size_t index
)
168 vlc_playlist_AssertLocked(playlist
);
169 return playlist
->items
.data
[index
];
173 vlc_playlist_IndexOf(vlc_playlist_t
*playlist
, const vlc_playlist_item_t
*item
)
175 vlc_playlist_AssertLocked(playlist
);
178 vlc_vector_index_of(&playlist
->items
, item
, &index
);
183 vlc_playlist_IndexOfMedia(vlc_playlist_t
*playlist
, const input_item_t
*media
)
185 vlc_playlist_AssertLocked(playlist
);
187 playlist_item_vector_t
*items
= &playlist
->items
;
188 for (size_t i
= 0; i
< items
->size
; ++i
)
189 if (items
->data
[i
]->media
== media
)
195 vlc_playlist_Clear(vlc_playlist_t
*playlist
)
197 vlc_playlist_AssertLocked(playlist
);
199 int ret
= vlc_player_SetCurrentMedia(playlist
->player
, NULL
);
200 VLC_UNUSED(ret
); /* what could we do? */
202 vlc_playlist_ClearItems(playlist
);
203 vlc_playlist_ItemsReset(playlist
);
207 vlc_playlist_MediaToItems(input_item_t
*const media
[], size_t count
,
208 vlc_playlist_item_t
*items
[])
211 for (i
= 0; i
< count
; ++i
)
213 items
[i
] = vlc_playlist_item_New(media
[i
]);
214 if (unlikely(!items
[i
]))
219 /* allocation failure, release partial items */
221 vlc_playlist_item_Release(items
[--i
]);
228 vlc_playlist_Insert(vlc_playlist_t
*playlist
, size_t index
,
229 input_item_t
*const media
[], size_t count
)
231 vlc_playlist_AssertLocked(playlist
);
232 assert(index
<= playlist
->items
.size
);
234 /* make space in the vector */
235 if (!vlc_vector_insert_hole(&playlist
->items
, index
, count
))
238 /* create playlist items in place */
239 int ret
= vlc_playlist_MediaToItems(media
, count
,
240 &playlist
->items
.data
[index
]);
241 if (ret
!= VLC_SUCCESS
)
243 /* we were optimistic, it failed, restore the vector state */
244 vlc_vector_remove_slice(&playlist
->items
, index
, count
);
248 vlc_playlist_ItemsInserted(playlist
, index
, count
);
249 vlc_player_InvalidateNextMedia(playlist
->player
);
255 vlc_playlist_Move(vlc_playlist_t
*playlist
, size_t index
, size_t count
,
258 vlc_playlist_AssertLocked(playlist
);
259 assert(index
+ count
<= playlist
->items
.size
);
260 assert(target
+ count
<= playlist
->items
.size
);
262 vlc_vector_move_slice(&playlist
->items
, index
, count
, target
);
264 vlc_playlist_ItemsMoved(playlist
, index
, count
, target
);
265 vlc_player_InvalidateNextMedia(playlist
->player
);
269 vlc_playlist_Remove(vlc_playlist_t
*playlist
, size_t index
, size_t count
)
271 vlc_playlist_AssertLocked(playlist
);
272 assert(index
< playlist
->items
.size
);
274 vlc_playlist_ItemsRemoving(playlist
, index
, count
);
276 for (size_t i
= 0; i
< count
; ++i
)
277 vlc_playlist_item_Release(playlist
->items
.data
[index
+ i
]);
279 vlc_vector_remove_slice(&playlist
->items
, index
, count
);
281 bool current_media_changed
= vlc_playlist_ItemsRemoved(playlist
, index
,
283 if (current_media_changed
)
284 vlc_playlist_SetCurrentMedia(playlist
, playlist
->current
);
286 vlc_player_InvalidateNextMedia(playlist
->player
);
290 vlc_playlist_Expand(vlc_playlist_t
*playlist
, size_t index
,
291 input_item_t
*const media
[], size_t count
)
293 vlc_playlist_AssertLocked(playlist
);
294 assert(index
< playlist
->items
.size
);
296 vlc_playlist_RemoveOne(playlist
, index
);
297 return vlc_playlist_Insert(playlist
, index
, media
, count
);