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
);
93 libvlc_renderer_item_t
*
94 libvlc_renderer_item_hold(libvlc_renderer_item_t
*p_item
)
96 vlc_renderer_item_hold( (vlc_renderer_item_t
*) p_item
);
101 libvlc_renderer_item_release(libvlc_renderer_item_t
*p_item
)
103 vlc_renderer_item_release( (vlc_renderer_item_t
*) p_item
);
107 libvlc_renderer_item_name( const libvlc_renderer_item_t
*p_item
)
109 return vlc_renderer_item_name( (const vlc_renderer_item_t
*) p_item
);
113 libvlc_renderer_item_type( const libvlc_renderer_item_t
*p_item
)
115 return vlc_renderer_item_type( (const vlc_renderer_item_t
*) p_item
);
119 libvlc_renderer_item_icon_uri( const libvlc_renderer_item_t
*p_item
)
121 return vlc_renderer_item_icon_uri( (const vlc_renderer_item_t
*) p_item
);
125 libvlc_renderer_item_flags( const libvlc_renderer_item_t
*p_item
)
127 return vlc_renderer_item_flags( (const vlc_renderer_item_t
*) p_item
);
130 libvlc_renderer_discoverer_t
*
131 libvlc_renderer_discoverer_new( libvlc_instance_t
*p_inst
,
132 const char *psz_name
)
134 size_t len
= strlen( psz_name
) + 1;
135 libvlc_renderer_discoverer_t
*p_lrd
= malloc( sizeof(*p_lrd
) + len
);
137 if( unlikely(p_lrd
== NULL
) )
140 p_lrd
->p_object
= VLC_OBJECT(p_inst
->p_libvlc_int
);
141 memcpy( p_lrd
->name
, psz_name
, len
);
142 TAB_INIT( p_lrd
->i_items
, p_lrd
->pp_items
);
144 libvlc_event_manager_init( &p_lrd
->event_manager
, p_lrd
);
150 libvlc_renderer_discoverer_release( libvlc_renderer_discoverer_t
*p_lrd
)
152 libvlc_renderer_discoverer_stop( p_lrd
);
153 libvlc_event_manager_destroy( &p_lrd
->event_manager
);
158 libvlc_renderer_discoverer_start( libvlc_renderer_discoverer_t
*p_lrd
)
160 assert( p_lrd
->p_rd
== NULL
);
162 struct vlc_renderer_discovery_owner owner
=
165 renderer_discovery_item_added
,
166 renderer_discovery_item_removed
,
169 p_lrd
->p_rd
= vlc_rd_new( p_lrd
->p_object
, p_lrd
->name
, &owner
);
170 return p_lrd
->p_rd
!= NULL
? 0 : -1;
174 libvlc_renderer_discoverer_stop( libvlc_renderer_discoverer_t
*p_lrd
)
176 if( p_lrd
->p_rd
!= NULL
)
177 vlc_rd_release( p_lrd
->p_rd
);
179 for( int i
= 0; i
< p_lrd
->i_items
; ++i
)
180 vlc_renderer_item_release( p_lrd
->pp_items
[i
] );
181 TAB_CLEAN( p_lrd
->i_items
, p_lrd
->pp_items
);
184 libvlc_event_manager_t
*
185 libvlc_renderer_discoverer_event_manager( libvlc_renderer_discoverer_t
*p_lrd
)
187 return &p_lrd
->event_manager
;
191 libvlc_renderer_discoverer_list_release( libvlc_rd_description_t
**pp_services
,
196 for( size_t i
= 0; i
< i_count
; ++i
)
198 free( pp_services
[i
]->psz_name
);
199 free( pp_services
[i
]->psz_longname
);
201 free( *pp_services
);
207 libvlc_renderer_discoverer_list_get( libvlc_instance_t
*p_inst
,
208 libvlc_rd_description_t
***ppp_services
)
210 assert( p_inst
!= NULL
&& ppp_services
!= NULL
);
212 /* Fetch all rd names, and longnames */
213 char **ppsz_names
, **ppsz_longnames
;
214 int i_ret
= vlc_rd_get_names( p_inst
->p_libvlc_int
, &ppsz_names
,
217 if( i_ret
!= VLC_SUCCESS
)
219 *ppp_services
= NULL
;
223 /* Count the number of sd matching our category (i_cat/i_core_cat) */
224 size_t i_nb_services
= 0;
225 char **ppsz_name
= ppsz_names
;
226 for( ; *ppsz_name
!= NULL
; ppsz_name
++ )
229 libvlc_rd_description_t
**pp_services
= NULL
,
231 if( i_nb_services
> 0 )
233 /* Double alloc here, so that the caller iterates through pointers of
234 * struct instead of structs. This allows us to modify the struct
235 * without breaking the API. */
238 malloc( i_nb_services
239 * sizeof(libvlc_rd_description_t
*) );
241 malloc( i_nb_services
242 * sizeof(libvlc_rd_description_t
) );
243 if( pp_services
== NULL
|| p_services
== NULL
)
250 /* Even if alloc fails, the next loop must be run in order to free
251 * names returned by vlc_sd_GetNames */
255 /* Fill output pp_services or free unused name, longname */
256 char **ppsz_longname
= ppsz_longnames
;
257 unsigned int i_service_idx
= 0;
258 libvlc_rd_description_t
*p_service
= p_services
;
259 for( ppsz_name
= ppsz_names
; *ppsz_name
!= NULL
; ppsz_name
++, ppsz_longname
++ )
261 if( pp_services
!= NULL
)
263 p_service
->psz_name
= *ppsz_name
;
264 p_service
->psz_longname
= *ppsz_longname
;
265 pp_services
[i_service_idx
++] = p_service
++;
270 free( *ppsz_longname
);
274 free( ppsz_longnames
);
276 *ppp_services
= pp_services
;
277 return i_nb_services
;