1 /*****************************************************************************
2 * renderer_discoverer.c: libvlc renderer API
3 *****************************************************************************
4 * Copyright © 2016 VLC authors and VideoLAN
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.
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.
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 *****************************************************************************/
27 #include <vlc/libvlc.h>
28 #include <vlc/libvlc_renderer_discoverer.h>
30 #include <vlc_common.h>
32 #include "libvlc_internal.h"
33 #include "renderer_discoverer_internal.h"
35 struct libvlc_renderer_discoverer_t
37 libvlc_event_manager_t event_manager
;
38 vlc_object_t
* p_object
;
39 vlc_renderer_discovery_t
*p_rd
;
42 vlc_renderer_item_t
** pp_items
;
46 static_assert( VLC_RENDERER_CAN_AUDIO
== LIBVLC_RENDERER_CAN_AUDIO
&&
47 VLC_RENDERER_CAN_VIDEO
== LIBVLC_RENDERER_CAN_VIDEO
,
48 "core/libvlc renderer flags mismatch" );
50 const vlc_renderer_item_t
*
51 libvlc_renderer_item_to_vlc( const libvlc_renderer_item_t
*p_item
)
53 return (const vlc_renderer_item_t
*) p_item
;
56 static void renderer_discovery_item_added( vlc_renderer_discovery_t
*rd
,
57 vlc_renderer_item_t
*p_item
)
59 libvlc_renderer_discoverer_t
*p_lrd
= rd
->owner
.sys
;
61 vlc_renderer_item_hold( p_item
);
63 TAB_APPEND( p_lrd
->i_items
, p_lrd
->pp_items
, p_item
);
65 libvlc_event_t event
= {
66 .type
= libvlc_RendererDiscovererItemAdded
,
67 .u
.renderer_discoverer_item_added
.item
=
68 (libvlc_renderer_item_t
*) p_item
,
70 libvlc_event_send( &p_lrd
->event_manager
, &event
);
73 static void renderer_discovery_item_removed( vlc_renderer_discovery_t
*rd
,
74 vlc_renderer_item_t
*p_item
)
76 libvlc_renderer_discoverer_t
*p_lrd
= rd
->owner
.sys
;
79 TAB_FIND( p_lrd
->i_items
, p_lrd
->pp_items
, p_item
, i_idx
);
80 assert( i_idx
!= -1 );
81 TAB_ERASE( p_lrd
->i_items
, p_lrd
->pp_items
, i_idx
);
83 libvlc_event_t event
= {
84 .type
= libvlc_RendererDiscovererItemDeleted
,
85 .u
.renderer_discoverer_item_deleted
.item
=
86 (libvlc_renderer_item_t
*) p_item
,
88 libvlc_event_send( &p_lrd
->event_manager
, &event
);
90 vlc_renderer_item_release( p_item
);
94 libvlc_renderer_item_name( const libvlc_renderer_item_t
*p_item
)
96 return vlc_renderer_item_name( (vlc_renderer_item_t
*) p_item
);
100 libvlc_renderer_item_type( const libvlc_renderer_item_t
*p_item
)
102 return vlc_renderer_item_type( (vlc_renderer_item_t
*) p_item
);
106 libvlc_renderer_item_icon_uri( const libvlc_renderer_item_t
*p_item
)
108 return vlc_renderer_item_icon_uri( (vlc_renderer_item_t
*) p_item
);
112 libvlc_renderer_item_flags( const libvlc_renderer_item_t
*p_item
)
114 return vlc_renderer_item_flags( (vlc_renderer_item_t
*) p_item
);
117 libvlc_renderer_discoverer_t
*
118 libvlc_renderer_discoverer_new( libvlc_instance_t
*p_inst
,
119 const char *psz_name
)
121 size_t len
= strlen( psz_name
) + 1;
122 libvlc_renderer_discoverer_t
*p_lrd
= malloc( sizeof(*p_lrd
) + len
);
124 if( unlikely(p_lrd
== NULL
) )
127 p_lrd
->p_object
= VLC_OBJECT(p_inst
->p_libvlc_int
);
128 memcpy( p_lrd
->name
, psz_name
, len
);
129 TAB_INIT( p_lrd
->i_items
, p_lrd
->pp_items
);
131 libvlc_event_manager_init( &p_lrd
->event_manager
, p_lrd
);
137 libvlc_renderer_discoverer_release( libvlc_renderer_discoverer_t
*p_lrd
)
139 libvlc_renderer_discoverer_stop( p_lrd
);
140 libvlc_event_manager_destroy( &p_lrd
->event_manager
);
145 libvlc_renderer_discoverer_start( libvlc_renderer_discoverer_t
*p_lrd
)
147 assert( p_lrd
->p_rd
== NULL
);
149 struct vlc_renderer_discovery_owner owner
=
152 renderer_discovery_item_added
,
153 renderer_discovery_item_removed
,
156 p_lrd
->p_rd
= vlc_rd_new( p_lrd
->p_object
, p_lrd
->name
, &owner
);
157 return p_lrd
->p_rd
!= NULL
? 0 : -1;
161 libvlc_renderer_discoverer_stop( libvlc_renderer_discoverer_t
*p_lrd
)
163 if( p_lrd
->p_rd
!= NULL
)
164 vlc_rd_release( p_lrd
->p_rd
);
166 for( int i
= 0; i
< p_lrd
->i_items
; ++i
)
167 vlc_renderer_item_release( p_lrd
->pp_items
[i
] );
168 TAB_CLEAN( p_lrd
->i_items
, p_lrd
->pp_items
);
171 libvlc_event_manager_t
*
172 libvlc_renderer_discoverer_event_manager( libvlc_renderer_discoverer_t
*p_lrd
)
174 return &p_lrd
->event_manager
;
178 libvlc_renderer_discoverer_list_release( libvlc_rd_description_t
**pp_services
,
183 for( size_t i
= 0; i
< i_count
; ++i
)
185 free( pp_services
[i
]->psz_name
);
186 free( pp_services
[i
]->psz_longname
);
188 free( *pp_services
);
194 libvlc_renderer_discoverer_list_get( libvlc_instance_t
*p_inst
,
195 libvlc_rd_description_t
***ppp_services
)
197 assert( p_inst
!= NULL
&& ppp_services
!= NULL
);
199 /* Fetch all rd names, and longnames */
200 char **ppsz_names
, **ppsz_longnames
;
201 int i_ret
= vlc_rd_get_names( p_inst
->p_libvlc_int
, &ppsz_names
,
204 if( i_ret
!= VLC_SUCCESS
)
206 *ppp_services
= NULL
;
210 /* Count the number of sd matching our category (i_cat/i_core_cat) */
211 size_t i_nb_services
= 0;
212 char **ppsz_name
= ppsz_names
;
213 for( ; *ppsz_name
!= NULL
; ppsz_name
++ )
216 libvlc_rd_description_t
**pp_services
= NULL
,
218 if( i_nb_services
> 0 )
220 /* Double alloc here, so that the caller iterates through pointers of
221 * struct instead of structs. This allows us to modify the struct
222 * without breaking the API. */
225 malloc( i_nb_services
226 * sizeof(libvlc_rd_description_t
*) );
228 malloc( i_nb_services
229 * sizeof(libvlc_rd_description_t
) );
230 if( pp_services
== NULL
|| p_services
== NULL
)
237 /* Even if alloc fails, the next loop must be run in order to free
238 * names returned by vlc_sd_GetNames */
242 /* Fill output pp_services or free unused name, longname */
243 char **ppsz_longname
= ppsz_longnames
;
244 unsigned int i_service_idx
= 0;
245 libvlc_rd_description_t
*p_service
= p_services
;
246 for( ppsz_name
= ppsz_names
; *ppsz_name
!= NULL
; ppsz_name
++, ppsz_longname
++ )
248 if( pp_services
!= NULL
)
250 p_service
->psz_name
= *ppsz_name
;
251 p_service
->psz_longname
= *ppsz_longname
;
252 pp_services
[i_service_idx
++] = p_service
++;
257 free( *ppsz_longname
);
261 free( ppsz_longnames
);
263 *ppp_services
= pp_services
;
264 return i_nb_services
;