/src/vlc/src/playlist/preparse.c
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * playlist/preparse.c |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2018 VLC authors and VideoLAN |
5 | | * |
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. |
10 | | * |
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. |
15 | | * |
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 | | *****************************************************************************/ |
20 | | |
21 | | #ifdef HAVE_CONFIG_H |
22 | | # include "config.h" |
23 | | #endif |
24 | | |
25 | | #include "preparse.h" |
26 | | |
27 | | #include "content.h" |
28 | | #include "item.h" |
29 | | #include "playlist.h" |
30 | | #include "notify.h" |
31 | | #include "libvlc.h" /* for vlc_MetadataRequest() */ |
32 | | |
33 | | typedef struct VLC_VECTOR(input_item_t *) media_vector_t; |
34 | | |
35 | | static void |
36 | | vlc_playlist_CollectChildren(vlc_playlist_t *playlist, |
37 | | media_vector_t *dest, |
38 | | input_item_node_t *node) |
39 | 0 | { |
40 | 0 | vlc_playlist_AssertLocked(playlist); |
41 | 0 | for (int i = 0; i < node->i_children; ++i) |
42 | 0 | { |
43 | 0 | input_item_node_t *child = node->pp_children[i]; |
44 | 0 | input_item_t *media = child->p_item; |
45 | 0 | vlc_vector_push(dest, media); |
46 | 0 | vlc_playlist_CollectChildren(playlist, dest, child); |
47 | 0 | } |
48 | 0 | } |
49 | | |
50 | | int |
51 | | vlc_playlist_ExpandItem(vlc_playlist_t *playlist, size_t index, |
52 | | input_item_node_t *node) |
53 | 0 | { |
54 | 0 | vlc_playlist_AssertLocked(playlist); |
55 | |
|
56 | 0 | media_vector_t flatten = VLC_VECTOR_INITIALIZER; |
57 | 0 | vlc_playlist_CollectChildren(playlist, &flatten, node); |
58 | |
|
59 | 0 | int ret = vlc_playlist_Expand(playlist, index, flatten.data, flatten.size); |
60 | 0 | vlc_vector_destroy(&flatten); |
61 | |
|
62 | 0 | return ret; |
63 | 0 | } |
64 | | |
65 | | int |
66 | | vlc_playlist_ExpandItemFromNode(vlc_playlist_t *playlist, |
67 | | input_item_node_t *subitems) |
68 | 0 | { |
69 | 0 | vlc_playlist_AssertLocked(playlist); |
70 | 0 | input_item_t *media = subitems->p_item; |
71 | 0 | ssize_t index = vlc_playlist_IndexOfMedia(playlist, media); |
72 | 0 | if (index == -1) |
73 | 0 | return VLC_ENOENT; |
74 | | |
75 | | /* replace the item by its flatten subtree */ |
76 | 0 | return vlc_playlist_ExpandItem(playlist, index, subitems); |
77 | 0 | } |
78 | | |
79 | | static void |
80 | | on_subtree_added(input_item_t *media, input_item_node_t *subtree, |
81 | | void *userdata) |
82 | 0 | { |
83 | 0 | VLC_UNUSED(media); /* retrieved by subtree->p_item */ |
84 | 0 | vlc_playlist_t *playlist = userdata; |
85 | |
|
86 | 0 | vlc_playlist_Lock(playlist); |
87 | 0 | vlc_playlist_ExpandItemFromNode(playlist, subtree); |
88 | 0 | vlc_playlist_Unlock(playlist); |
89 | 0 | } |
90 | | |
91 | | static void |
92 | | on_preparse_ended(input_item_t *media, |
93 | | enum input_item_preparse_status status, void *userdata) |
94 | 0 | { |
95 | 0 | VLC_UNUSED(media); /* retrieved by subtree->p_item */ |
96 | 0 | vlc_playlist_t *playlist = userdata; |
97 | |
|
98 | 0 | if (status != ITEM_PREPARSE_DONE) |
99 | 0 | return; |
100 | | |
101 | 0 | vlc_playlist_Lock(playlist); |
102 | 0 | ssize_t index = vlc_playlist_IndexOfMedia(playlist, media); |
103 | 0 | if (index != -1) |
104 | 0 | vlc_playlist_Notify(playlist, on_items_updated, index, |
105 | 0 | &playlist->items.data[index], 1); |
106 | 0 | vlc_playlist_Unlock(playlist); |
107 | 0 | } |
108 | | |
109 | | static const input_preparser_callbacks_t input_preparser_callbacks = { |
110 | | .on_preparse_ended = on_preparse_ended, |
111 | | .on_subtree_added = on_subtree_added, |
112 | | }; |
113 | | |
114 | | void |
115 | | vlc_playlist_Preparse(vlc_playlist_t *playlist, input_item_t *input) |
116 | 0 | { |
117 | | #ifdef TEST_PLAYLIST |
118 | | VLC_UNUSED(playlist); |
119 | | VLC_UNUSED(input); |
120 | | VLC_UNUSED(input_preparser_callbacks); |
121 | | #else |
122 | | /* vlc_MetadataRequest is not exported */ |
123 | 0 | vlc_MetadataRequest(playlist->libvlc, input, |
124 | 0 | META_REQUEST_OPTION_SCOPE_LOCAL | |
125 | 0 | META_REQUEST_OPTION_FETCH_LOCAL, |
126 | 0 | &input_preparser_callbacks, playlist, -1, NULL); |
127 | 0 | #endif |
128 | 0 | } |
129 | | |
130 | | void |
131 | | vlc_playlist_AutoPreparse(vlc_playlist_t *playlist, input_item_t *input) |
132 | 0 | { |
133 | 0 | if (playlist->auto_preparse && !input_item_IsPreparsed(input)) |
134 | 0 | vlc_playlist_Preparse(playlist, input); |
135 | 0 | } |