1 /*****************************************************************************
2  * services_discovery.c : Manage playlist services_discovery modules
3  *****************************************************************************
4  * Copyright (C) 1999-2004 VLC authors and VideoLAN
5  * $Id: 12a029ef6e6e2c18dd81fea94a69a0f1d38a1144 $
6  *
7  * Authors: Clément Stenac <zorglub@videolan.org>
8  *
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.
13  *
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.
18  *
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>
27 
28 #include <vlc_common.h>
29 #include <vlc_services_discovery.h>
30 #include <vlc_probe.h>
31 #include <vlc_modules.h>
32 #include "../libvlc.h"
33 
34 typedef struct
35 {
36     char *name;
37     char *longname;
38     int category;
39 } vlc_sd_probe_t;
40 
vlc_sd_probe_Add(vlc_probe_t * probe,const char * name,const char * longname,int category)41 int vlc_sd_probe_Add (vlc_probe_t *probe, const char *name,
42                       const char *longname, int category)
43 {
44     vlc_sd_probe_t names = { strdup(name), strdup(longname), category };
45 
46     if (unlikely (names.name == NULL || names.longname == NULL
47                || vlc_probe_add (probe, &names, sizeof (names))))
48     {
49         free (names.name);
50         free (names.longname);
51         return VLC_ENOMEM;
52     }
53     return VLC_PROBE_CONTINUE;
54 }
55 
56 #undef vlc_sd_GetNames
57 
58 /**
59  * Gets the list of available services discovery plugins.
60  */
vlc_sd_GetNames(vlc_object_t * obj,char *** pppsz_longnames,int ** pp_categories)61 char **vlc_sd_GetNames (vlc_object_t *obj, char ***pppsz_longnames, int **pp_categories)
62 {
63     size_t count;
64     vlc_sd_probe_t *tab = vlc_probe (obj, "services probe", &count);
65 
66     if (count == 0)
67     {
68         free (tab);
69         return NULL;
70     }
71 
72     char **names = vlc_alloc (count + 1, sizeof(char *));
73     char **longnames = vlc_alloc (count + 1, sizeof(char *));
74     int *categories = vlc_alloc (count + 1, sizeof(int));
75 
76     if (unlikely (names == NULL || longnames == NULL || categories == NULL))
77     {
78         free(names);
79         free(longnames);
80         free(categories);
81         free(tab);
82         return NULL;
83     }
84     for( size_t i = 0; i < count; i++ )
85     {
86         names[i] = tab[i].name;
87         longnames[i] = tab[i].longname;
88         categories[i] = tab[i].category;
89     }
90     free (tab);
91     names[count] = longnames[count] = NULL;
92     categories[count] = 0;
93     *pppsz_longnames = longnames;
94     if( pp_categories ) *pp_categories = categories;
95     else free( categories );
96     return names;
97 }
98 
99 /*
100  * Services discovery
101  * Basically you just listen to Service discovery event through the
102  * sd's event manager.
103  * That's how the playlist get's Service Discovery information
104  */
105 
vlc_sd_Create(vlc_object_t * parent,const char * cfg,const struct services_discovery_owner_t * restrict owner)106 services_discovery_t *vlc_sd_Create(vlc_object_t *parent, const char *cfg,
107     const struct services_discovery_owner_t *restrict owner)
108 {
109     services_discovery_t *sd = vlc_custom_create(parent, sizeof (*sd),
110                                                  "services discovery");
111     if (unlikely(sd == NULL))
112         return NULL;
113 
114     free(config_ChainCreate(&sd->psz_name, &sd->p_cfg, cfg));
115     sd->description = NULL;
116     sd->owner = *owner;
117 
118     sd->p_module = module_need(sd, "services_discovery",
119                                sd->psz_name, true);
120     if (sd->p_module == NULL)
121     {
122         msg_Err(sd, "no suitable services discovery module");
123         vlc_sd_Destroy(sd);
124         sd = NULL;
125     }
126 
127     return sd;
128 }
129 
vlc_sd_Destroy(services_discovery_t * sd)130 void vlc_sd_Destroy(services_discovery_t *sd)
131 {
132     if (sd->p_module != NULL)
133         module_unneed(sd, sd->p_module);
134     config_ChainDestroy(sd->p_cfg);
135     free(sd->psz_name);
136     vlc_object_release(sd);
137 }
138