@interface VLCMain : NSObject <NSWindowDelegate, NSApplicationDelegate>
{
intf_thread_t *p_intf; /* The main intf object */
- input_thread_t *p_current_input, *p_input_changed;
+ input_thread_t *p_current_input;
BOOL launched; /* finishedLaunching */
int items_at_launch; /* items in playlist after launch */
id o_mainmenu; /* VLCMainMenu */
NSTimer *o_itunes_play_timer;
BOOL b_playlist_updated_selector_in_queue;
+
+ dispatch_queue_t informInputChangedQueue;
}
@property (readonly) VLCVoutWindowController* voutController;
- (BOOL)hasDefinedShortcutKey:(NSEvent *)o_event force:(BOOL)b_force;
- (void)PlaylistItemChanged;
-- (void)informInputChanged;
- (void)playbackStatusUpdated;
- (void)sendDistributedNotificationWithUpdatedPlaybackStatus;
- (void)playbackModeUpdated;
* Run: main loop
*****************************************************************************/
static NSLock * o_appLock = nil; // controls access to f_appExit
-static NSLock * o_plItemChangedLock = nil;
static void Run(intf_thread_t *p_intf)
{
[VLCApplication sharedApplication];
o_appLock = [[NSLock alloc] init];
- o_plItemChangedLock = [[NSLock alloc] init];
o_vout_provider_lock = [[NSLock alloc] init];
libvlc_SetExitHandler(p_intf->p_libvlc, QuitVLC, p_intf);
[NSApp run];
[[VLCMain sharedInstance] applicationWillTerminate:nil];
- [o_plItemChangedLock release];
[o_appLock release];
[o_vout_provider_lock release];
o_vout_provider_lock = nil;
{
NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
- /* Due to constraints within NSAttributedString's main loop runtime handling
- * and other issues, we need to wait for -PlaylistItemChanged to finish and
- * then -informInputChanged on this non-main thread. */
- [o_plItemChangedLock lock];
- [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(PlaylistItemChanged) withObject:nil waitUntilDone:YES]; // MUST BE ON MAIN THREAD
- [[VLCMain sharedInstance] informInputChanged]; // DO NOT MOVE TO MAIN THREAD
- [o_plItemChangedLock unlock];
+ [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(PlaylistItemChanged) withObject:nil waitUntilDone:NO];
[o_pool release];
return VLC_SUCCESS;
_o_sharedMainInstance = [super init];
p_intf = NULL;
- p_current_input = p_input_changed = NULL;
+ p_current_input = NULL;
o_open = [[VLCOpen alloc] init];
o_coredialogs = [[VLCCoreDialogProvider alloc] init];
o_vout_controller = [[VLCVoutWindowController alloc] init];
+ informInputChangedQueue = dispatch_queue_create("org.videolan.vlc.inputChangedQueue", DISPATCH_QUEUE_SERIAL);
+
return _o_sharedMainInstance;
}
// This must be called on main thread
- (void)PlaylistItemChanged
{
+ input_thread_t *p_input_changed = nil;
+
if (p_current_input && (p_current_input->b_dead || !vlc_object_alive(p_current_input))) {
var_DelCallback(p_current_input, "intf-event", InputEvent, [VLCMain sharedInstance]);
p_input_changed = p_current_input;
[o_mainwindow updateWindow];
[self updateDelays];
[self updateMainMenu];
-}
-- (void)informInputChanged
-{
+ /*
+ * Due to constraints within NSAttributedString's main loop runtime handling
+ * and other issues, we need to inform the extension manager on a separate thread.
+ * The serial queue ensures that changed inputs are propagated in the same order as they arrive.
+ */
if (p_input_changed) {
- [[ExtensionsManager getInstance:p_intf] inputChanged:p_input_changed];
- vlc_object_release(p_input_changed);
- p_input_changed = NULL;
+ dispatch_async(informInputChangedQueue, ^{
+ [[ExtensionsManager getInstance:p_intf] inputChanged:p_input_changed];
+ vlc_object_release(p_input_changed);
+ });
}
}