thread: use posix thread code for darwin
[vlc.git] / src / misc / renderer_discovery.c
1 /*****************************************************************************
2  * renderer_discovery.c : Renderer Discovery functions
3  *****************************************************************************
4  * Copyright(C) 2016 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 <assert.h>
26
27 #include <vlc_common.h>
28 #include <vlc_atomic.h>
29 #include <vlc_renderer_discovery.h>
30 #include <vlc_probe.h>
31 #include <vlc_modules.h>
32 #include <libvlc.h>
33
34 struct vlc_renderer_item_t
35 {
36     char *psz_name;
37     char *psz_type;
38     char *psz_sout;
39     char *psz_icon_uri;
40     char *psz_demux_filter;
41     int i_flags;
42     vlc_atomic_rc_t rc;
43 };
44
45 static void
46 item_free(vlc_renderer_item_t *p_item)
47 {
48     free(p_item->psz_name);
49     free(p_item->psz_type);
50     free(p_item->psz_sout);
51     free(p_item->psz_icon_uri);
52     free(p_item->psz_demux_filter);
53     free(p_item);
54 }
55
56 vlc_renderer_item_t *
57 vlc_renderer_item_new(const char *psz_type, const char *psz_name,
58                       const char *psz_uri, const char *psz_extra_sout,
59                       const char *psz_demux_filter, const char *psz_icon_uri,
60                       int i_flags)
61 {
62     assert(psz_uri != NULL);
63     vlc_renderer_item_t *p_item = NULL;
64     vlc_url_t url;
65     vlc_UrlParse(&url, psz_uri);
66
67     if (url.psz_protocol == NULL || url.psz_host == NULL)
68         goto error;
69
70     p_item = calloc(1, sizeof(vlc_renderer_item_t));
71     if (unlikely(p_item == NULL))
72         goto error;
73
74     if ((p_item->psz_type = strdup(psz_type)) == NULL)
75         goto error;
76
77     if (psz_name != NULL)
78         p_item->psz_name = strdup(psz_name);
79     else if (asprintf(&p_item->psz_name, "%s (%s)", url.psz_protocol,
80                       url.psz_host) == -1)
81         p_item->psz_name = NULL;
82     if (p_item->psz_name == NULL)
83         goto error;
84
85     if (asprintf(&p_item->psz_sout, "%s{ip=%s,port=%u%s%s}",
86                  url.psz_protocol, url.psz_host, url.i_port,
87                  psz_extra_sout != NULL ? "," : "",
88                  psz_extra_sout != NULL ? psz_extra_sout : "") == -1)
89         goto error;
90
91     if (psz_icon_uri && (p_item->psz_icon_uri = strdup(psz_icon_uri)) == NULL)
92         goto error;
93
94     if (psz_demux_filter && (p_item->psz_demux_filter = strdup(psz_demux_filter)) == NULL)
95         goto error;
96
97     p_item->i_flags = i_flags;
98     vlc_atomic_rc_init(&p_item->rc);
99     vlc_UrlClean(&url);
100     return p_item;
101
102 error:
103     vlc_UrlClean(&url);
104     if (p_item != NULL)
105         item_free(p_item);
106     return NULL;
107 }
108
109 const char *
110 vlc_renderer_item_name(const vlc_renderer_item_t *p_item)
111 {
112     assert(p_item != NULL);
113
114     return p_item->psz_name;
115 }
116
117 const char *
118 vlc_renderer_item_type(const vlc_renderer_item_t *p_item)
119 {
120     assert(p_item != NULL);
121
122     return p_item->psz_type;
123 }
124
125 const char *
126 vlc_renderer_item_sout(const vlc_renderer_item_t *p_item)
127 {
128     assert(p_item != NULL);
129
130     return p_item->psz_sout;
131 }
132
133 const char *
134 vlc_renderer_item_icon_uri(const vlc_renderer_item_t *p_item)
135 {
136     assert(p_item != NULL);
137
138     return p_item->psz_icon_uri;
139 }
140
141 const char *
142 vlc_renderer_item_demux_filter(const vlc_renderer_item_t *p_item)
143 {
144     assert(p_item != NULL);
145
146     return p_item->psz_demux_filter;
147 }
148
149 int
150 vlc_renderer_item_flags(const vlc_renderer_item_t *p_item)
151 {
152     assert(p_item != NULL);
153
154     return p_item->i_flags;
155 }
156
157 vlc_renderer_item_t *
158 vlc_renderer_item_hold(vlc_renderer_item_t *p_item)
159 {
160     assert(p_item != NULL);
161
162     vlc_atomic_rc_inc(&p_item->rc);
163     return p_item;
164 }
165
166 void
167 vlc_renderer_item_release(vlc_renderer_item_t *p_item)
168 {
169     assert(p_item != NULL);
170
171     if (vlc_atomic_rc_dec(&p_item->rc))
172         item_free(p_item);
173 }
174
175 struct vlc_rd_probe
176 {
177     char *psz_name;
178     char *psz_longname;
179 };
180
181 int
182 vlc_rd_probe_add(vlc_probe_t *probe, const char *psz_name,
183                  const char *psz_longname)
184 {
185     struct vlc_rd_probe names = { strdup(psz_name), strdup(psz_longname) };
186
187     if (unlikely(names.psz_name == NULL || names.psz_longname == NULL
188                  || vlc_probe_add(probe, &names, sizeof(names))))
189     {
190         free(names.psz_name);
191         free(names.psz_longname);
192         return VLC_ENOMEM;
193     }
194     return VLC_PROBE_CONTINUE;
195 }
196
197 #undef vlc_rd_get_names
198 int
199 vlc_rd_get_names(vlc_object_t *p_obj, char ***pppsz_names,
200                  char ***pppsz_longnames)
201 {
202     size_t i_count;
203     struct vlc_rd_probe *p_tab = vlc_probe(p_obj, "renderer probe", &i_count);
204
205     if (i_count == 0)
206     {
207         free(p_tab);
208         return VLC_EGENERIC;
209     }
210
211     char **ppsz_names = vlc_alloc(i_count + 1, sizeof(char *));
212     char **ppsz_longnames = vlc_alloc(i_count + 1, sizeof(char *));
213
214     if (unlikely(ppsz_names == NULL || ppsz_longnames == NULL))
215     {
216         free(ppsz_names);
217         free(ppsz_longnames);
218         free(p_tab);
219         return VLC_EGENERIC;
220     }
221
222     for (size_t i = 0; i < i_count; i++)
223     {
224         ppsz_names[i] = p_tab[i].psz_name;
225         ppsz_longnames[i] = p_tab[i].psz_longname;
226     }
227     ppsz_names[i_count] = ppsz_longnames[i_count] = NULL;
228     free(p_tab);
229     *pppsz_names = ppsz_names;
230     *pppsz_longnames = ppsz_longnames;
231     return VLC_SUCCESS;
232 }
233
234 void vlc_rd_release(vlc_renderer_discovery_t *p_rd)
235 {
236     module_unneed(p_rd, p_rd->p_module);
237     config_ChainDestroy(p_rd->p_cfg);
238     free(p_rd->psz_name);
239     vlc_object_delete(p_rd);
240 }
241
242 vlc_renderer_discovery_t *
243 vlc_rd_new(vlc_object_t *p_obj, const char *psz_name,
244            const struct vlc_renderer_discovery_owner *restrict owner)
245 {
246     vlc_renderer_discovery_t *p_rd;
247
248     p_rd = vlc_custom_create(p_obj, sizeof(*p_rd), "renderer discovery");
249     if(!p_rd)
250         return NULL;
251     free(config_ChainCreate(&p_rd->psz_name, &p_rd->p_cfg, psz_name));
252
253     p_rd->owner = *owner;
254     p_rd->p_module = module_need(p_rd, "renderer_discovery",
255                                  p_rd->psz_name, true);
256     if (p_rd->p_module == NULL)
257     {
258         msg_Err(p_rd, "no suitable renderer discovery module for '%s'",
259             psz_name);
260         free(p_rd->psz_name);
261         config_ChainDestroy(p_rd->p_cfg);
262         vlc_object_delete(p_rd);
263         p_rd = NULL;
264     }
265
266     return p_rd;
267 }