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