1 /*****************************************************************************
2 * VLCTime.h: VLC.framework VLCTime implementation
3 *****************************************************************************
4 * Copyright (C) 2007 Pierre d'Herbemont
5 * Copyright (C) 2007 the VideoLAN team
8 * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #import "VLCEventManager.h"
28 static VLCEventManager * defaultManager = NULL;
33 VLCObjectMethodWithObjectArg
44 enum message_type_t type;
47 @interface VLCEventManager (PrivateAPI)
49 - (void)callDelegateOfObjectAndSendNotificationWithArgs:(NSData*)data;
50 - (void)callObjectMethodWithArgs:(NSData*)data;
51 - (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName;
52 - (pthread_cond_t *)signalData;
53 - (pthread_mutex_t *)queueLock;
54 - (NSMutableArray *)messageQueue;
58 static void * EventDispatcherMainLoop(void * user_data)
60 VLCEventManager * self = user_data;
64 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
65 struct message * message, * message_newer = NULL;
69 /* Wait for some data */
70 pthread_mutex_lock( [self queueLock] );
72 /* Wait until we have something on the queue */
73 while([[self messageQueue] count] <= 0 )
75 pthread_cond_wait( [self signalData], [self queueLock] );
77 message = (struct message *)[(NSData *)[[self messageQueue] lastObject] bytes];
79 /* Don't send the same notification twice */
80 if( message->type == VLCNotification )
82 for( i = 0; i < [[self messageQueue] count]-1; i++ )
84 message_newer = (struct message *)[(NSData *)[[self messageQueue] objectAtIndex: i] bytes];
85 if( message_newer->type != VLCNotification )
88 if( message_newer->target == message->target && message_newer->target == message->target && [message_newer->u.name isEqualToString:message->u.name] )
90 [message_newer->target release];
91 [message->u.name release];
92 [[self messageQueue] removeObjectAtIndex: i];
98 dataMessage = [[self messageQueue] lastObject];
100 pthread_mutex_unlock( [self queueLock] );
102 if( message->type == VLCNotification )
103 [self performSelectorOnMainThread:@selector(callDelegateOfObjectAndSendNotificationWithArgs:) withObject:[dataMessage retain] waitUntilDone: NO];
105 [self performSelectorOnMainThread:@selector(callObjectMethodWithArgs:) withObject:[dataMessage retain] waitUntilDone: NO];
107 pthread_mutex_lock( [self queueLock] );
108 [[self messageQueue] removeLastObject];
109 pthread_mutex_unlock( [self queueLock] );
116 @implementation VLCEventManager
120 /* We do want a lock here to avoid leaks */
121 if ( !defaultManager )
123 defaultManager = [[VLCEventManager alloc] init];
126 return defaultManager;
131 if( self = [super init] )
133 pthread_mutex_init( &queueLock, NULL );
134 pthread_cond_init( &signalData, NULL );
135 pthread_create( &dispatcherThread, NULL, EventDispatcherMainLoop, self );
136 messageQueue = [[NSMutableArray alloc] initWithCapacity:10];
143 pthread_kill( dispatcherThread, SIGKILL );
144 pthread_join( dispatcherThread, NULL );
146 [messageQueue release];
150 - (void)callOnMainThreadDelegateOfObject:(id)aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName
152 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
154 struct message message =
158 [aNotificationName retain],
162 pthread_mutex_lock( [self queueLock] );
163 [[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
164 pthread_cond_signal( [self signalData] );
165 pthread_mutex_unlock( [self queueLock] );
170 - (void)callOnMainThreadObject:(id)aTarget withMethod:(SEL)aSelector withArgumentAsObject: (id)arg
172 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
174 struct message message =
179 VLCObjectMethodWithObjectArg
182 pthread_mutex_lock( [self queueLock] );
183 [[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
184 pthread_cond_signal( [self signalData] );
185 pthread_mutex_unlock( [self queueLock] );
191 @implementation VLCEventManager (PrivateAPI)
193 - (void)callDelegateOfObjectAndSendNotificationWithArgs:(NSData*)data
195 struct message * message = (struct message *)[data bytes];
197 [self callDelegateOfObject:message->target withDelegateMethod:message->sel withNotificationName:message->u.name];
198 [message->u.name release];
199 [message->target release];
203 - (void)callObjectMethodWithArgs:(NSData*)data
205 struct message * message = (struct message *)[data bytes];
206 void (*method)(id, SEL, id) = (void (*)(id, SEL, id))[message->target methodForSelector: message->sel];
208 method( message->target, message->sel, message->u.object);
209 [message->u.object release];
210 [message->target release];
214 - (NSMutableArray *)messageQueue
219 - (pthread_cond_t *)signalData
224 - (pthread_mutex_t *)queueLock
229 - (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName
231 // [[NSNotificationCenter defaultCenter] postNotification: [NSNotification notificationWithName:aNotificationName object:aTarget]];
233 if (![aTarget delegate] || ![[aTarget delegate] respondsToSelector: aSelector])
236 void (*method)(id, SEL, id) = (void (*)(id, SEL, id))[[aTarget delegate] methodForSelector: aSelector];
237 method( [aTarget delegate], aSelector, [NSNotification notificationWithName:aNotificationName object:aTarget]);