0
# Media Discovery and Renderers
1
2
Network media discovery, renderer discovery for casting, and media library management capabilities. These features enable building applications that can discover network media sources and cast to remote devices.
3
4
## Capabilities
5
6
### Media Discovery
7
8
The MediaDiscoverer class provides network media discovery capabilities for finding media sources on the network.
9
10
```python { .api }
11
class MediaDiscoverer:
12
def __init__(self, instance, service_name):
13
"""Create a media discoverer.
14
15
Args:
16
instance (Instance): VLC instance
17
service_name (str): Name of discovery service
18
"""
19
...
20
21
def start(self):
22
"""Start the media discovery service.
23
24
Returns:
25
int: 0 on success, -1 on error
26
"""
27
...
28
29
def stop(self):
30
"""Stop the media discovery service."""
31
...
32
33
def media_list(self):
34
"""Get the media list discovered by this service.
35
36
Returns:
37
MediaList: List of discovered media items
38
"""
39
...
40
41
def event_manager(self):
42
"""Get the event manager for this media discoverer.
43
44
Returns:
45
EventManager: Event manager for discovery events
46
"""
47
...
48
49
def is_running(self):
50
"""Check if the discoverer is currently running.
51
52
Returns:
53
bool: True if running, False otherwise
54
"""
55
...
56
57
def release(self):
58
"""Release the media discoverer."""
59
...
60
```
61
62
### Media Discovery Services
63
64
Static methods for enumerating available discovery services.
65
66
```python { .api }
67
@staticmethod
68
def media_discoverer_list_get(instance, category):
69
"""Get list of available media discovery services.
70
71
Args:
72
instance (Instance): VLC instance
73
category (MediaDiscovererCategory): Category of services to list
74
75
Returns:
76
list: List of (service_name, long_name) tuples
77
"""
78
...
79
80
@staticmethod
81
def media_discoverer_list_release(services_list):
82
"""Release a media discoverer services list.
83
84
Args:
85
services_list (list): List returned by media_discoverer_list_get
86
"""
87
...
88
```
89
90
### Renderer Discovery
91
92
The RendererDiscoverer class provides discovery of renderers (casting targets) on the network.
93
94
```python { .api }
95
class RendererDiscoverer:
96
def __init__(self, instance, service_name):
97
"""Create a renderer discoverer.
98
99
Args:
100
instance (Instance): VLC instance
101
service_name (str): Name of renderer discovery service
102
"""
103
...
104
105
def start(self):
106
"""Start the renderer discovery service.
107
108
Returns:
109
int: 0 on success, -1 on error
110
"""
111
...
112
113
def stop(self):
114
"""Stop the renderer discovery service."""
115
...
116
117
def event_manager(self):
118
"""Get the event manager for this renderer discoverer.
119
120
Returns:
121
EventManager: Event manager for renderer events
122
"""
123
...
124
125
def release(self):
126
"""Release the renderer discoverer."""
127
...
128
```
129
130
### Renderer Management
131
132
The Renderer class represents discovered casting targets.
133
134
```python { .api }
135
class Renderer:
136
def name(self):
137
"""Get the renderer name.
138
139
Returns:
140
str: Human-readable name of the renderer
141
"""
142
...
143
144
def type(self):
145
"""Get the renderer type.
146
147
Returns:
148
str: Type of renderer (e.g., "chromecast", "upnp")
149
"""
150
...
151
152
def icon_uri(self):
153
"""Get the renderer icon URI.
154
155
Returns:
156
str: URI to renderer icon or None
157
"""
158
...
159
160
def flags(self):
161
"""Get renderer capability flags.
162
163
Returns:
164
int: Bitfield of renderer capabilities
165
"""
166
...
167
168
def can_render_audio(self):
169
"""Check if renderer can handle audio.
170
171
Note: Not directly available - check flags() & RendererFlags.Audio
172
173
Returns:
174
bool: True if can render audio
175
"""
176
return (self.flags() & vlc.RendererFlags.Audio) != 0
177
178
def can_render_video(self):
179
"""Check if renderer can handle video.
180
181
Note: Not directly available - check flags() & RendererFlags.Video
182
183
Returns:
184
bool: True if can render video
185
"""
186
return (self.flags() & vlc.RendererFlags.Video) != 0
187
188
def hold(self):
189
"""Hold a reference to this renderer.
190
191
Returns:
192
Renderer: This renderer instance
193
"""
194
...
195
196
def release(self):
197
"""Release this renderer."""
198
...
199
```
200
201
### Renderer Discovery Services
202
203
Static methods for managing renderer discovery services.
204
205
```python { .api }
206
@staticmethod
207
def renderer_discoverer_list_get(instance):
208
"""Get list of available renderer discovery services.
209
210
Args:
211
instance (Instance): VLC instance
212
213
Returns:
214
list: List of (service_name, long_name) tuples
215
"""
216
...
217
218
@staticmethod
219
def renderer_discoverer_list_release(services_list):
220
"""Release a renderer discoverer services list.
221
222
Args:
223
services_list (list): List returned by renderer_discoverer_list_get
224
"""
225
...
226
```
227
228
### Media Player Renderer Integration
229
230
Methods on MediaPlayer for using discovered renderers.
231
232
```python { .api }
233
# Renderer methods on MediaPlayer
234
def set_renderer(self, renderer):
235
"""Set a renderer for casting output.
236
237
Args:
238
renderer (Renderer): Renderer to cast to, or None to stop casting
239
240
Returns:
241
int: 0 on success, -1 on error
242
"""
243
...
244
```
245
246
### Discovery Categories
247
248
Enumeration for media discovery service categories.
249
250
```python { .api }
251
class MediaDiscovererCategory:
252
"""Media discovery service categories."""
253
Devices = 0
254
Lan = 1
255
Podcasts = 2
256
LocalDirs = 3
257
```
258
259
### Discovery Event Types
260
261
Event types for discovery operations.
262
263
```python { .api }
264
class EventType:
265
# Media Discoverer Events
266
MediaDiscovererStarted = 0x500
267
MediaDiscovererEnded = 0x501
268
269
# Renderer Discoverer Events
270
RendererDiscovererItemAdded = 0x700
271
RendererDiscovererItemDeleted = 0x701
272
```
273
274
### Renderer Flags
275
276
Capability flags for renderers.
277
278
```python { .api }
279
class RendererFlags:
280
"""Renderer capability flags."""
281
Audio = 0x01
282
Video = 0x02
283
284
# Usage: Check renderer capabilities with bitwise operations
285
# has_audio = (renderer.flags() & vlc.RendererFlags.Audio) != 0
286
# has_video = (renderer.flags() & vlc.RendererFlags.Video) != 0
287
```
288
289
## Usage Examples
290
291
### Media Discovery Basic Usage
292
293
```python
294
import vlc
295
import time
296
297
def on_discoverer_started(event):
298
print("Media discoverer started")
299
300
def on_discoverer_ended(event):
301
print("Media discoverer ended")
302
303
# Create instance and list available discovery services
304
instance = vlc.Instance()
305
services = vlc.MediaDiscoverer.media_discoverer_list_get(
306
instance, vlc.MediaDiscovererCategory.Lan
307
)
308
309
print("Available LAN discovery services:")
310
for service_name, long_name in services:
311
print(f" {service_name}: {long_name}")
312
313
if services:
314
# Create discoverer for first service
315
service_name = services[0][0]
316
discoverer = vlc.MediaDiscoverer(instance, service_name)
317
318
# Attach events
319
em = discoverer.event_manager()
320
em.event_attach(vlc.EventType.MediaDiscovererStarted, on_discoverer_started)
321
em.event_attach(vlc.EventType.MediaDiscovererEnded, on_discoverer_ended)
322
323
# Start discovery
324
print(f"Starting discovery with service: {service_name}")
325
discoverer.start()
326
327
# Wait for discovery
328
time.sleep(5)
329
330
# Get discovered media
331
media_list = discoverer.media_list()
332
if media_list:
333
count = media_list.count()
334
print(f"Discovered {count} media items:")
335
336
for i in range(count):
337
media = media_list.item_at_index(i)
338
if media:
339
mrl = media.get_mrl()
340
print(f" {i}: {mrl}")
341
342
# Stop discovery
343
discoverer.stop()
344
discoverer.release()
345
346
# Clean up
347
vlc.MediaDiscoverer.media_discoverer_list_release(services)
348
```
349
350
### Comprehensive Media Discovery
351
352
```python
353
import vlc
354
import time
355
356
class MediaDiscoveryManager:
357
def __init__(self, instance):
358
self.instance = instance
359
self.discoverers = []
360
self.discovered_media = {}
361
362
def discover_all_categories(self):
363
"""Start discovery for all available categories."""
364
categories = [
365
vlc.MediaDiscovererCategory.Devices,
366
vlc.MediaDiscovererCategory.Lan,
367
vlc.MediaDiscovererCategory.Podcasts,
368
vlc.MediaDiscovererCategory.LocalDirs
369
]
370
371
category_names = ["Devices", "LAN", "Podcasts", "Local Directories"]
372
373
for category, name in zip(categories, category_names):
374
print(f"\n=== {name} Discovery ===")
375
services = vlc.MediaDiscoverer.media_discoverer_list_get(
376
self.instance, category
377
)
378
379
if not services:
380
print(f"No {name.lower()} discovery services available")
381
continue
382
383
for service_name, long_name in services:
384
print(f"Starting {service_name}: {long_name}")
385
386
try:
387
discoverer = vlc.MediaDiscoverer(self.instance, service_name)
388
em = discoverer.event_manager()
389
390
# Setup events with service context
391
em.event_attach(
392
vlc.EventType.MediaDiscovererStarted,
393
lambda e, sn=service_name: self.on_started(e, sn)
394
)
395
em.event_attach(
396
vlc.EventType.MediaDiscovererEnded,
397
lambda e, sn=service_name: self.on_ended(e, sn)
398
)
399
400
discoverer.start()
401
self.discoverers.append((service_name, discoverer))
402
403
except Exception as e:
404
print(f"Failed to start {service_name}: {e}")
405
406
vlc.MediaDiscoverer.media_discoverer_list_release(services)
407
408
def on_started(self, event, service_name):
409
print(f"β {service_name} discovery started")
410
411
def on_ended(self, event, service_name):
412
print(f"β {service_name} discovery ended")
413
414
def collect_discovered_media(self):
415
"""Collect all discovered media from active discoverers."""
416
print("\n=== Discovered Media ===")
417
418
for service_name, discoverer in self.discoverers:
419
if discoverer.is_running():
420
media_list = discoverer.media_list()
421
if media_list:
422
count = media_list.count()
423
if count > 0:
424
print(f"\n{service_name} ({count} items):")
425
items = []
426
427
for i in range(count):
428
media = media_list.item_at_index(i)
429
if media:
430
mrl = media.get_mrl()
431
items.append(mrl)
432
print(f" {i+1}: {mrl}")
433
434
self.discovered_media[service_name] = items
435
436
def stop_all(self):
437
"""Stop all discoverers."""
438
print("\nStopping all discoverers...")
439
for service_name, discoverer in self.discoverers:
440
discoverer.stop()
441
discoverer.release()
442
self.discoverers.clear()
443
444
# Usage
445
instance = vlc.Instance()
446
manager = MediaDiscoveryManager(instance)
447
448
# Start discovery for all categories
449
manager.discover_all_categories()
450
451
# Wait for discovery
452
print("\nWaiting for discovery to complete...")
453
time.sleep(10)
454
455
# Collect results
456
manager.collect_discovered_media()
457
458
# Stop all discoverers
459
manager.stop_all()
460
461
# Summary
462
print(f"\nDiscovered media in {len(manager.discovered_media)} services:")
463
for service, items in manager.discovered_media.items():
464
print(f" {service}: {len(items)} items")
465
```
466
467
### Renderer Discovery and Casting
468
469
```python
470
import vlc
471
import time
472
473
def on_renderer_added(event):
474
"""Handle renderer discovered."""
475
renderer = event.u.item
476
print(f"β Renderer discovered: {renderer.name()} ({renderer.type()})")
477
478
def on_renderer_deleted(event):
479
"""Handle renderer removed."""
480
renderer = event.u.item
481
print(f"β Renderer removed: {renderer.name()}")
482
483
# Create instance and list renderer discovery services
484
instance = vlc.Instance()
485
services = vlc.RendererDiscoverer.renderer_discoverer_list_get(instance)
486
487
print("Available renderer discovery services:")
488
for service_name, long_name in services:
489
print(f" {service_name}: {long_name}")
490
491
discovered_renderers = []
492
493
if services:
494
# Start discovery for all renderer services
495
discoverers = []
496
497
for service_name, long_name in services:
498
try:
499
print(f"Starting {service_name} renderer discovery...")
500
rd = vlc.RendererDiscoverer(instance, service_name)
501
502
# Attach events
503
em = rd.event_manager()
504
em.event_attach(vlc.EventType.RendererDiscovererItemAdded, on_renderer_added)
505
em.event_attach(vlc.EventType.RendererDiscovererItemDeleted, on_renderer_deleted)
506
507
rd.start()
508
discoverers.append(rd)
509
510
except Exception as e:
511
print(f"Failed to start {service_name}: {e}")
512
513
# Wait for renderer discovery
514
print("\nDiscovering renderers...")
515
time.sleep(10)
516
517
# Create a media player for casting test
518
player = vlc.MediaPlayer('/path/to/video.mp4')
519
520
# Example: Cast to first discovered renderer (if any)
521
# Note: This is conceptual - actual renderer objects would come from events
522
print("\nTesting casting (conceptual example):")
523
print("To cast to a renderer, you would:")
524
print("1. Get renderer from discovery events")
525
print("2. Use player.set_renderer(renderer)")
526
print("3. Start playback with player.play()")
527
528
# Stop all discoverers
529
print("\nStopping renderer discovery...")
530
for rd in discoverers:
531
rd.stop()
532
rd.release()
533
534
# Clean up
535
vlc.RendererDiscoverer.renderer_discoverer_list_release(services)
536
```
537
538
### Advanced Renderer Discovery with Event Handling
539
540
```python
541
import vlc
542
import time
543
544
class RendererManager:
545
def __init__(self, instance):
546
self.instance = instance
547
self.discoverers = []
548
self.available_renderers = {}
549
550
def start_discovery(self):
551
"""Start discovery for all available renderer services."""
552
services = vlc.RendererDiscoverer.renderer_discoverer_list_get(self.instance)
553
554
print("Starting renderer discovery...")
555
for service_name, long_name in services:
556
try:
557
rd = vlc.RendererDiscoverer(self.instance, service_name)
558
em = rd.event_manager()
559
560
# Bind events with service context
561
em.event_attach(
562
vlc.EventType.RendererDiscovererItemAdded,
563
lambda e, sn=service_name: self.on_renderer_added(e, sn)
564
)
565
em.event_attach(
566
vlc.EventType.RendererDiscovererItemDeleted,
567
lambda e, sn=service_name: self.on_renderer_deleted(e, sn)
568
)
569
570
rd.start()
571
self.discoverers.append((service_name, rd))
572
print(f" Started {service_name}: {long_name}")
573
574
except Exception as e:
575
print(f" Failed to start {service_name}: {e}")
576
577
vlc.RendererDiscoverer.renderer_discoverer_list_release(services)
578
579
def on_renderer_added(self, event, service_name):
580
"""Handle renderer discovered."""
581
renderer = event.u.item
582
renderer_id = f"{service_name}:{renderer.name()}"
583
584
# Store renderer info
585
flags = renderer.flags()
586
self.available_renderers[renderer_id] = {
587
'name': renderer.name(),
588
'type': renderer.type(),
589
'service': service_name,
590
'can_audio': (flags & vlc.RendererFlags.Audio) != 0,
591
'can_video': (flags & vlc.RendererFlags.Video) != 0,
592
'icon_uri': renderer.icon_uri(),
593
'renderer_obj': renderer.hold() # Keep reference
594
}
595
596
print(f"πΊ Found renderer: {renderer.name()}")
597
print(f" Type: {renderer.type()}")
598
print(f" Audio: {'β' if (flags & vlc.RendererFlags.Audio) else 'β'}")
599
print(f" Video: {'β' if (flags & vlc.RendererFlags.Video) else 'β'}")
600
if renderer.icon_uri():
601
print(f" Icon: {renderer.icon_uri()}")
602
603
def on_renderer_deleted(self, event, service_name):
604
"""Handle renderer removed."""
605
renderer = event.u.item
606
renderer_id = f"{service_name}:{renderer.name()}"
607
608
if renderer_id in self.available_renderers:
609
# Release held reference
610
self.available_renderers[renderer_id]['renderer_obj'].release()
611
del self.available_renderers[renderer_id]
612
print(f"πΊ Renderer removed: {renderer.name()}")
613
614
def list_renderers(self):
615
"""List all currently available renderers."""
616
print(f"\nAvailable renderers ({len(self.available_renderers)}):")
617
for renderer_id, info in self.available_renderers.items():
618
print(f" {renderer_id}")
619
print(f" Type: {info['type']}")
620
print(f" Capabilities: Audio={info['can_audio']}, Video={info['can_video']}")
621
622
def cast_to_renderer(self, renderer_id, media_path):
623
"""Cast media to a specific renderer."""
624
if renderer_id not in self.available_renderers:
625
print(f"Renderer {renderer_id} not available")
626
return None
627
628
info = self.available_renderers[renderer_id]
629
renderer_obj = info['renderer_obj']
630
631
print(f"Casting to {info['name']}...")
632
633
# Create player and set renderer
634
player = vlc.MediaPlayer(media_path)
635
result = player.set_renderer(renderer_obj)
636
637
if result == 0:
638
print("β Renderer set successfully")
639
player.play()
640
return player
641
else:
642
print("β Failed to set renderer")
643
return None
644
645
def stop_discovery(self):
646
"""Stop all renderer discovery."""
647
print("Stopping renderer discovery...")
648
649
# Release all held renderer references
650
for info in self.available_renderers.values():
651
info['renderer_obj'].release()
652
self.available_renderers.clear()
653
654
# Stop and release discoverers
655
for service_name, rd in self.discoverers:
656
rd.stop()
657
rd.release()
658
self.discoverers.clear()
659
660
# Usage example
661
instance = vlc.Instance()
662
renderer_mgr = RendererManager(instance)
663
664
# Start discovery
665
renderer_mgr.start_discovery()
666
667
# Wait for discovery
668
print("Waiting for renderer discovery...")
669
time.sleep(15)
670
671
# List found renderers
672
renderer_mgr.list_renderers()
673
674
# Example casting (if renderers found)
675
if renderer_mgr.available_renderers:
676
first_renderer = list(renderer_mgr.available_renderers.keys())[0]
677
print(f"\nAttempting to cast to: {first_renderer}")
678
679
# Cast to first available renderer
680
player = renderer_mgr.cast_to_renderer(first_renderer, '/path/to/video.mp4')
681
682
if player:
683
print("Casting for 10 seconds...")
684
time.sleep(10)
685
player.stop()
686
687
# Stop casting by clearing renderer
688
player.set_renderer(None)
689
print("Stopped casting")
690
691
# Clean up
692
renderer_mgr.stop_discovery()
693
```
694
695
### Media Discovery with Playback
696
697
```python
698
import vlc
699
import time
700
701
# Discover and play network media
702
instance = vlc.Instance()
703
704
# Get UPnP discovery service
705
services = vlc.MediaDiscoverer.media_discoverer_list_get(
706
instance, vlc.MediaDiscovererCategory.Lan
707
)
708
709
upnp_service = None
710
for service_name, long_name in services:
711
if 'upnp' in service_name.lower():
712
upnp_service = service_name
713
break
714
715
if upnp_service:
716
print(f"Using UPnP discovery service: {upnp_service}")
717
718
# Create discoverer
719
discoverer = vlc.MediaDiscoverer(instance, upnp_service)
720
discoverer.start()
721
722
# Wait for discovery
723
print("Discovering UPnP media servers...")
724
time.sleep(8)
725
726
# Get discovered media
727
media_list = discoverer.media_list()
728
if media_list and media_list.count() > 0:
729
print(f"Found {media_list.count()} UPnP media sources")
730
731
# Play first discovered media
732
first_media = media_list.item_at_index(0)
733
if first_media:
734
print(f"Playing: {first_media.get_mrl()}")
735
736
player = vlc.MediaPlayer()
737
player.set_media(first_media)
738
player.play()
739
740
# Play for a while
741
time.sleep(30)
742
player.stop()
743
else:
744
print("No UPnP media servers found")
745
746
# Clean up
747
discoverer.stop()
748
discoverer.release()
749
else:
750
print("No UPnP discovery service available")
751
752
vlc.MediaDiscoverer.media_discoverer_list_release(services)
753
```