[vlc-commits] [Git][videolan/vlc][master] 3 commits: macosx/renderer-discovery: run callbacks on main-thread
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Thu May 28 14:03:37 UTC 2026
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
9b4c8a5c by Felix Paul Kühne at 2026-05-28T15:51:49+02:00
macosx/renderer-discovery: run callbacks on main-thread
- - - - -
53b2153e by Felix Paul Kühne at 2026-05-28T15:51:49+02:00
macosx/renderer menu: fix missing init and move data handling to MT
- - - - -
dd296d71 by Felix Paul Kühne at 2026-05-28T15:51:49+02:00
macosx/renderer-discovery: zero delegate on dealloc
Fixes a crash when a discovery callback fires on the main thread
after the delegate has been deallocated. The assign property left
a dangling pointer; weak makes ARC zero it on dealloc.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSXPCInterfaceProxy_NSOSPServiceExportedToHostProtocol removedRendererItem:from:]:
unrecognized selector sent to instance 0x7479c1cc0'
*** First throw call stack:
(
0 CoreFoundation 0x000000018fb491c0 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000018f5d291c objc_exception_throw + 88
2 CoreFoundation 0x000000018fc0a250 -[NSObject(NSObject) __retain_OA] + 0
3 CoreFoundation 0x000000018fab9f38 ___forwarding___ + 1480
4 CoreFoundation 0x000000018fab98b0 _CF_forwarding_prep_0 + 96
5 libmacosx_plugin.dylib 0x0000000108158598 __42-[VLCRendererDiscovery handleItemRemoved:]_block_invoke + 500
6 libdispatch.dylib 0x000000018f862a28 _dispatch_call_block_and_release + 32
- - - - -
3 changed files:
- modules/gui/macosx/menus/renderers/VLCRendererDiscovery.h
- modules/gui/macosx/menus/renderers/VLCRendererDiscovery.m
- modules/gui/macosx/menus/renderers/VLCRendererMenuController.m
Changes:
=====================================
modules/gui/macosx/menus/renderers/VLCRendererDiscovery.h
=====================================
@@ -39,7 +39,7 @@ extern NSString * const VLCRendererRemovedNotification;
/**
The delegate that is called when a \c VLCRendererItem is added or deleted
*/
- at property (assign) id<VLCRendererDiscoveryDelegate> delegate;
+ at property (weak) id<VLCRendererDiscoveryDelegate> delegate;
/**
The name of the renderer discovery module
=====================================
modules/gui/macosx/menus/renderers/VLCRendererDiscovery.m
=====================================
@@ -38,7 +38,7 @@ NSString * const VLCRendererRemovedNotification = @"VLCRendererRemovedNotificati
}
- (void)handleItemAdded:(vlc_renderer_item_t *)item;
-- (void)handleItemRemoved:(const vlc_renderer_item_t *)item;
+- (void)handleItemRemoved:(vlc_renderer_item_t *)item;
@end
@@ -120,32 +120,38 @@ static void renderer_event_item_removed(vlc_renderer_discovery_t *rd,
- (void)handleItemAdded:(vlc_renderer_item_t *)base_item
{
VLCRendererItem *item = [[VLCRendererItem alloc] initWithRendererItem:base_item];
- [_rendererItems addObject:item];
- if (_delegate)
- [_delegate addedRendererItem:item from:self];
-
- [NSNotificationCenter.defaultCenter postNotificationName:VLCRendererAddedNotification
- object:item];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self->_rendererItems addObject:item];
+ if (self->_delegate)
+ [self->_delegate addedRendererItem:item from:self];
+
+ [NSNotificationCenter.defaultCenter postNotificationName:VLCRendererAddedNotification
+ object:item];
+ });
}
-- (void)handleItemRemoved:(const vlc_renderer_item_t *)base_item
+- (void)handleItemRemoved:(vlc_renderer_item_t *)base_item
{
- VLCRendererItem *result_item = nil;
- for (VLCRendererItem *item in _rendererItems) {
- if (item.rendererItem == base_item) {
- result_item = item;
- break;
+ VLCRendererItem * const removedItem =
+ [[VLCRendererItem alloc] initWithRendererItem:base_item];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ VLCRendererItem *result_item = nil;
+ for (VLCRendererItem *item in self->_rendererItems) {
+ if (item.rendererItem == removedItem.rendererItem) {
+ result_item = item;
+ break;
+ }
}
- }
- if (result_item) {
- if (_delegate)
- [_delegate removedRendererItem:result_item from:self];
- [_rendererItems removeObject:result_item];
- [NSNotificationCenter.defaultCenter postNotificationName:VLCRendererRemovedNotification
- object:result_item];
- } else {
- msg_Err(p_intf, "VLCRendererDiscovery could not find item to remove!");
- }
+ if (result_item) {
+ if (self->_delegate)
+ [self->_delegate removedRendererItem:result_item from:self];
+ [self->_rendererItems removeObject:result_item];
+ [NSNotificationCenter.defaultCenter postNotificationName:VLCRendererRemovedNotification
+ object:result_item];
+ } else {
+ msg_Err(self->p_intf, "VLCRendererDiscovery could not find item to remove!");
+ }
+ });
}
@end
=====================================
modules/gui/macosx/menus/renderers/VLCRendererMenuController.m
=====================================
@@ -49,6 +49,7 @@
self = [super init];
if (self) {
_rendererDiscoveries = [NSMutableArray array];
+ _rendererItems = @[];
_isDiscoveryEnabled = NO;
p_intf = getIntf();
@@ -95,22 +96,20 @@
- (void)addRendererItem:(VLCRendererItem *)item
{
NSParameterAssert(item != nil);
+
NSMutableArray * const mutableRenderers = _rendererItems.mutableCopy;
[mutableRenderers addObject:item];
_rendererItems = mutableRenderers.copy;
// Check if the item is already selected
- if (_selectedItem.representedObject != nil)
- {
+ if (_selectedItem.representedObject != nil) {
VLCRendererItem *selected_rd_item = _selectedItem.representedObject;
- if ([selected_rd_item.identifier isEqualToString:item.identifier])
- {
+ if ([selected_rd_item.identifier isEqualToString:item.identifier]) {
[_selectedItem setRepresentedObject:item];
return;
}
}
- // Create a menu item
NSMenuItem *menuItem = [[NSMenuItem alloc] init];
menuItem.target = self;
menuItem.action = @selector(selectRenderer:);
@@ -129,31 +128,25 @@
range:[unformattedTitle rangeOfString:item.userReadableType options:NSBackwardsSearch]];
menuItem.attributedTitle = title;
- // The main menu must only be updated from the main thread
- dispatch_async(dispatch_get_main_queue(), ^{
- [_rendererMenu insertItem:menuItem atIndex:[_rendererMenu indexOfItem:_rendererNoneItem] + 1];
- });
+ [_rendererMenu insertItem:menuItem atIndex:[_rendererMenu indexOfItem:_rendererNoneItem] + 1];
}
- (void)removeRendererItem:(VLCRendererItem *)item
{
NSParameterAssert(item != nil);
- // The main menu must only be updated from the main thread
- dispatch_async(dispatch_get_main_queue(), ^{
- NSMutableArray * const mutableRenderers = _rendererItems.mutableCopy;
- [mutableRenderers removeObject:item];
- _rendererItems = mutableRenderers.copy;
-
- const NSInteger index = [_rendererMenu indexOfItemWithRepresentedObject:item];
- if (index >= 0) {
- NSMenuItem * const menuItem = [_rendererMenu itemAtIndex:index];
- // Don't remove selected item
- if (menuItem != _selectedItem) {
- [_rendererMenu removeItemAtIndex:index];
- }
+ NSMutableArray * const mutableRenderers = _rendererItems.mutableCopy;
+ [mutableRenderers removeObject:item];
+ _rendererItems = mutableRenderers.copy;
+
+ const NSInteger index = [_rendererMenu indexOfItemWithRepresentedObject:item];
+ if (index >= 0) {
+ NSMenuItem * const menuItem = [_rendererMenu itemAtIndex:index];
+ // Don't remove selected item
+ if (menuItem != _selectedItem) {
+ [_rendererMenu removeItemAtIndex:index];
}
- });
+ }
}
- (void)startRendererDiscoveries
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b766af16a3f43f02491b7d12d6527eb4d736a283...dd296d71e301429c24ed84d5ee221ec08b2ac956
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b766af16a3f43f02491b7d12d6527eb4d736a283...dd296d71e301429c24ed84d5ee221ec08b2ac956
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list