packetizer: hxxx: fix DirectTV extraction
[vlc.git] / src / playlist / services_discovery.c
blob39a43badd65764fee1673183272186237d4a842d
1 /*****************************************************************************
2 * services_discovery.c : Manage playlist services_discovery modules
3 *****************************************************************************
4 * Copyright (C) 1999-2004 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Clément Stenac <zorglub@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 #include <assert.h>
28 #include <vlc_common.h>
29 #include <vlc_playlist.h>
30 #include <vlc_services_discovery.h>
31 #include "playlist_internal.h"
33 struct vlc_sd_internal_t
35 /* the playlist items for category and onelevel */
36 playlist_item_t *node;
37 services_discovery_t *sd; /**< Loaded service discovery modules */
38 char name[];
41 /* A new item has been added to a certain sd */
42 static void playlist_sd_item_added(services_discovery_t *sd,
43 input_item_t *parent, input_item_t *p_input,
44 const char *psz_cat)
46 assert(parent == NULL || psz_cat == NULL);
48 vlc_sd_internal_t *sds = sd->owner.sys;
49 playlist_t *playlist = (playlist_t *)sd->obj.parent;
50 playlist_item_t *node;
51 const char *longname = (sd->description != NULL) ? sd->description : "?";
53 msg_Dbg(sd, "adding: %s", p_input->psz_name ? p_input->psz_name : "(null)");
55 playlist_Lock(playlist);
56 if (sds->node == NULL)
57 sds->node = playlist_NodeCreate(playlist, longname, &playlist->root,
58 PLAYLIST_END, PLAYLIST_RO_FLAG);
60 if (parent != NULL)
61 node = playlist_ItemGetByInput(playlist, parent);
62 else
63 if (psz_cat == NULL)
64 node = sds->node;
65 else
66 { /* Parent is NULL (root) and category is specified.
67 * This is clearly a hack. TODO: remove this. */
68 node = playlist_ChildSearchName(sds->node, psz_cat);
69 if (node == NULL)
70 node = playlist_NodeCreate(playlist, psz_cat, sds->node,
71 PLAYLIST_END, PLAYLIST_RO_FLAG);
74 playlist_NodeAddInput(playlist, p_input, node, PLAYLIST_END);
75 playlist_Unlock(playlist);
78 /* A new item has been removed from a certain sd */
79 static void playlist_sd_item_removed(services_discovery_t *sd,
80 input_item_t *p_input)
82 vlc_sd_internal_t *sds = sd->owner.sys;
83 playlist_t *playlist = (playlist_t *)sd->obj.parent;
84 playlist_item_t *node, *item;
86 msg_Dbg(sd, "removing: %s", p_input->psz_name ? p_input->psz_name : "(null)");
88 playlist_Lock(playlist);
89 item = playlist_ItemGetByInput(playlist, p_input);
90 if (unlikely(item == NULL))
92 msg_Err(sd, "removing item not added"); /* SD plugin bug */
93 playlist_Unlock(playlist);
94 return;
97 #ifndef NDEBUG
98 /* Check that the item belonged to the SD */
99 for (playlist_item_t *i = item->p_parent; i != sds->node; i = i->p_parent)
100 assert(i != NULL);
101 #endif
103 node = item->p_parent;
104 /* if the item was added under a category and the category node
105 becomes empty, delete that node as well */
106 if (node != sds->node && node->i_children == 1)
107 item = node;
108 playlist_NodeDeleteExplicit(playlist, item,
109 PLAYLIST_DELETE_FORCE | PLAYLIST_DELETE_STOP_IF_CURRENT );
110 playlist_Unlock(playlist);
113 int playlist_ServicesDiscoveryAdd(playlist_t *playlist, const char *chain)
115 vlc_sd_internal_t *sds = malloc(sizeof (*sds) + strlen(chain) + 1);
116 if (unlikely(sds == NULL))
117 return VLC_ENOMEM;
119 sds->node = NULL;
121 struct services_discovery_owner_t owner = {
122 sds,
123 playlist_sd_item_added,
124 playlist_sd_item_removed,
127 /* Perform the addition */
128 sds->sd = vlc_sd_Create(VLC_OBJECT(playlist), chain, &owner);
129 if (unlikely(sds->sd == NULL))
131 free(sds);
132 return VLC_ENOMEM;
135 strcpy(sds->name, chain);
137 playlist_Lock(playlist);
138 /* Backward compatibility with Qt UI: create the node even if the SD
139 * has not discovered any item. */
140 if (sds->node == NULL && sds->sd->description != NULL)
141 sds->node = playlist_NodeCreate(playlist, sds->sd->description,
142 &playlist->root, PLAYLIST_END,
143 PLAYLIST_RO_FLAG);
145 TAB_APPEND(pl_priv(playlist)->i_sds, pl_priv(playlist)->pp_sds, sds);
146 playlist_Unlock(playlist);
147 return VLC_SUCCESS;
150 static void playlist_ServicesDiscoveryInternalRemove(playlist_t *playlist,
151 vlc_sd_internal_t *sds)
153 assert(sds->sd != NULL);
154 vlc_sd_Destroy(sds->sd);
156 /* Remove the sd playlist node if it exists */
157 playlist_Lock(playlist);
158 if (sds->node != NULL)
159 playlist_NodeDeleteExplicit(playlist, sds->node,
160 PLAYLIST_DELETE_FORCE | PLAYLIST_DELETE_STOP_IF_CURRENT );
161 playlist_Unlock(playlist);
163 free(sds);
167 int playlist_ServicesDiscoveryRemove(playlist_t *playlist, const char *name)
169 playlist_private_t *priv = pl_priv(playlist);
170 vlc_sd_internal_t *sds = NULL;
172 playlist_Lock(playlist);
173 for (int i = 0; i < priv->i_sds; i++)
175 vlc_sd_internal_t *entry = priv->pp_sds[i];
177 if (!strcmp(name, entry->name))
179 TAB_ERASE(priv->i_sds, priv->pp_sds, i);
180 sds = entry;
181 break;
184 playlist_Unlock(playlist);
186 if (sds == NULL)
188 msg_Warn(playlist, "discovery %s is not loaded", name);
189 return VLC_EGENERIC;
192 playlist_ServicesDiscoveryInternalRemove(playlist, sds);
193 return VLC_SUCCESS;
196 bool playlist_IsServicesDiscoveryLoaded( playlist_t * playlist,
197 const char *psz_name )
199 playlist_private_t *priv = pl_priv( playlist );
200 bool found = false;
201 playlist_Lock(playlist);
203 for( int i = 0; i < priv->i_sds; i++ )
205 vlc_sd_internal_t *sds = priv->pp_sds[i];
207 if (!strcmp(psz_name, sds->name))
209 found = true;
210 break;
213 playlist_Unlock(playlist);
214 return found;
217 int playlist_ServicesDiscoveryControl( playlist_t *playlist, const char *psz_name, int i_control, ... )
219 playlist_private_t *priv = pl_priv( playlist );
220 int i_ret = VLC_EGENERIC;
221 int i;
223 playlist_Lock(playlist);
224 for( i = 0; i < priv->i_sds; i++ )
226 vlc_sd_internal_t *sds = priv->pp_sds[i];
227 if (!strcmp(psz_name, sds->name))
229 va_list args;
230 va_start( args, i_control );
231 i_ret = vlc_sd_control(sds->sd, i_control, args );
232 va_end( args );
233 break;
237 assert( i != priv->i_sds );
238 playlist_Unlock(playlist);
240 return i_ret;
243 void playlist_ServicesDiscoveryKillAll(playlist_t *playlist)
245 playlist_private_t *priv = pl_priv(playlist);
247 for (int i = 0; i < priv->i_sds; i++)
248 playlist_ServicesDiscoveryInternalRemove(playlist, priv->pp_sds[i]);
250 TAB_CLEAN(priv->i_sds, priv->pp_sds);