1#import "ESScreensaverView.h" 2#import "ESScreensaver.h" 3#import <OpenGL/OpenGL.h> 4#include "dlfcn.h" 5#include "libgen.h" 6 7NSOpenGLContext *glContext = NULL; 8 9bool bStarted = false; 10 11@implementation ESScreensaverView 12 13- (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview 14{ 15#ifdef SCREEN_SAVER 16 self = [super initWithFrame:frame isPreview:isPreview]; 17#else 18 self = [super initWithFrame:frame]; 19#endif 20 21 m_updater = NULL; 22 23 m_isFullScreen = !isPreview; 24 25 m_isPreview = isPreview; 26 27#ifdef SCREEN_SAVER 28 //if (isPreview) 29#endif 30 { 31 CFBundleRef bndl = CopyDLBundle_ex(); 32 NSBundle *nsbndl; 33 34 if (bndl != NULL) 35 { 36 NSURL* url = (NSURL*)CFBridgingRelease(CFBundleCopyBundleURL(bndl)); 37 38 nsbndl = [NSBundle bundleWithPath:[url path]]; 39 40 m_updater = [SUUpdater updaterForBundle:nsbndl]; 41 42 [m_updater setDelegate:self]; 43 44 if (m_updater && [m_updater automaticallyChecksForUpdates]) 45 { 46 [m_updater checkForUpdateInformation]; 47 } 48 49 CFRelease( bndl ); 50 } 51 } 52 53 if (self) 54 { 55 // So we modify the setup routines just a little bit to get our 56 // new OpenGL screensaver working. 57 58 // Create the new frame 59 NSRect newFrame = frame; 60 // Slam the origin values 61 newFrame.origin.x = 0.0; 62 newFrame.origin.y = 0.0; 63 64 theRect = newFrame; 65 // Now alloc and init the view, right from within the screen saver's initWithFrame: 66 67 // If the view is valid, we continue 68 //if(glView) 69 { 70 // Make sure we autoresize 71 [self setAutoresizesSubviews:YES]; 72 // So if our view is valid... 73 74 glView = NULL; 75 76 // Do some setup on our context and view 77 //[glView prepareOpenGL]; 78 // Then we set our animation loop timer 79 //[self setAnimationTimeInterval:1/60.0]; 80#ifdef SCREEN_SAVER 81 [self setAnimationTimeInterval:-1]; 82#endif 83 // Since our BasicOpenGLView class does it's setup in awakeFromNib, we call that here. 84 // Note that this could be any method you want to use as the setup routine for your view. 85 //[glView awakeFromNib]; 86 } 87 //else // Log an error if we fail here 88 // NSLog(@"Error: Electric Sheep Screen Saver failed to initialize NSOpenGLView!"); 89 } 90 // Finally return our newly-initialized self 91 return self; 92} 93 94- (void)startAnimation 95{ 96 /*NSMutableArray *displays = [NSMutableArray arrayWithCapacity:5]; 97 98 [displays addObject:[NSScreen mainScreen]]; 99 100 UInt32 cnt = [[NSScreen screens] count]; 101 102 for (int i=0; i<cnt; i++) 103 { 104 NSScreen *scr = [[NSScreen screens] objectAtIndex:i]; 105 106 if (scr != [NSScreen mainScreen]) 107 [displays addObject:scr]; 108 } 109 110 ESScreensaver_InitClientStorage(); 111 112 SInt32 scr = ESScreensaver_GetIntSetting("settings.player.screen", 0); 113 114 ESScreensaver_DeinitClientStorage(); 115 116 if (scr >= cnt) 117 scr = cnt - 1; 118 119 //main screen only for now? 120 if (!m_isPreview && [[self window] screen] != [displays objectAtIndex:scr]) 121 { 122 return; 123 } 124 else 125 {*/ 126 if (glView == NULL) 127 { 128 /*NSRect newRect; 129 130 newRect.size.height = theRect.size.height; 131 132 newRect.size.width = 800.0 * ( theRect.size.height / 592.0 ); 133 134 newRect.origin.x = theRect.origin.x + ( theRect.size.width - newRect.size.width ) / 2.0; 135 136 newRect.origin.y = theRect.origin.y; 137 138 theRect = newRect;*/ 139 140 glView = [[ESOpenGLView alloc] initWithFrame:theRect]; 141 142 if(glView) 143 { 144 glContext = [glView openGLContext]; 145 146 // We make it a subview of the screensaver view 147 [self addSubview:glView]; 148 } 149 } 150 //} 151 152 if (glView != NULL && [glView openGLContext]) 153 { 154 ESScreensaver_InitClientStorage(); 155 156 ESScreenSaver_AddGLContext( (CGLContextObj)[[glView openGLContext] CGLContextObj] ); 157 158 ESScreensaver_DeinitClientStorage(); 159 } 160 161 uint32 width = (uint32)theRect.size.width; 162 uint32 height = (uint32)theRect.size.height; 163 164#ifdef SCREEN_SAVER 165 m_isHidden = NO; 166#endif 167 168 if ( !bStarted ) 169 { 170 171 if (!ESScreensaver_Start( m_isPreview, width, height )) 172 return; 173 174 bStarted = true; 175 176 [self _beginThread]; 177 } 178#ifdef SCREEN_SAVER 179 [super startAnimation]; 180#endif 181} 182 183- (void)stopAnimation 184{ 185#ifdef SCREEN_SAVER 186 [NSCursor unhide]; 187#endif 188 if ( bStarted ) 189 { 190 [self _endThread]; 191 192 ESScreensaver_Stop(); 193 194 ESScreensaver_Deinit(); 195 196 bStarted = false; 197 } 198 199#ifdef SCREEN_SAVER 200 if (m_isHidden) 201 [NSCursor unhide]; 202 m_isHidden = NO; 203 [super stopAnimation]; 204#endif 205} 206 207- (void)animateOneFrame 208{ 209 //[self setAnimationTimeInterval:-1]; 210 211 //[animationLock unlock]; 212 213 //ESScreensaver_DoFrame(); 214 215 //[glView setNeedsDisplay:YES]; 216} 217 218- (void)_animationThread 219{ 220 @autoreleasepool { 221 222 if (animationLock != NULL) 223 [animationLock lock]; 224 225 while (!m_isStopped && !ESScreensaver_Stopped() && ESScreensaver_DoFrame()) 226 { 227#ifdef SCREEN_SAVER 228 if (!m_isPreview && CGCursorIsVisible()) 229 { 230 [NSCursor hide]; 231 m_isHidden = YES; 232 } 233#endif 234 //if (m_isStopped) 235 //break; 236 237 //if (glView != NULL) 238 //[glView setNeedsDisplay:YES]; 239 } 240 241 if (animationLock != NULL) 242 [animationLock unlock]; 243 244 } 245} 246 247- (void)_beginThread 248{ 249 animationLock = [[NSLock alloc] init]; 250 251 //[animationLock lock]; 252 253 m_isStopped = NO; 254 255 [NSThread detachNewThreadSelector:@selector(_animationThread) toTarget:self withObject:nil]; 256} 257 258- (void)_endThread 259{ 260 m_isStopped = YES; 261 262 [animationLock lock]; 263 [animationLock unlock]; 264 265 animationLock = NULL; 266} 267 268- (void)windowDidResize 269{ 270 [glView setFrame: [self frame]]; 271 272 ESScreensaver_ForceWidthAndHeight( (uint32)[self frame].size.width, (uint32)[self frame].size.height ); 273} 274 275 276- (BOOL)hasConfigureSheet 277{ 278 return YES; 279} 280 281- (NSWindow*)configureSheet 282{ 283 if (!m_config) { 284 m_config = [[ESConfiguration alloc] initWithWindowNibName:@"ElectricSheep" updater:m_updater]; 285 } 286 287 return [m_config window]; 288} 289 290- (void)flagsChanged:(NSEvent *)ev 291{ 292 if ([ev keyCode] == 63) //FN Key 293 return; 294 295 [super flagsChanged:ev]; 296} 297 298// keyDown 299// Capture Up/Down for rating animations 300// If there is no animation, or the computer cannot access the electricsheep server, UP and DOWN 301// act just like in a normal screensaver (they stop it) - initially I thought it should just ignore 302// the vote and not end playback (for consistency - UP/DOWN would never stop it) but I think it is 303// appropriate that if you can't vote, the default event behavior used 304 305//keycodes based on - http://www.filewatcher.com/p/BasiliskII-0.9.1.tgz.276457/share/BasiliskII/keycodes.html 306- (void) keyDown:(NSEvent *) ev 307{ 308 BOOL handled = NO; 309 310 NSString *characters = [ev charactersIgnoringModifiers]; 311 unsigned int characterIndex, characterCount = (unsigned int)[characters length]; 312 313 for (characterIndex = 0; characterIndex < characterCount; characterIndex++) { 314 unichar c = [characters characterAtIndex:characterIndex]; 315 switch (c) { 316 case NSRightArrowFunctionKey: 317 ESScreensaver_AppendKeyEvent( 0x7C ); 318 handled = YES; 319 break; 320 321 case NSLeftArrowFunctionKey: 322 ESScreensaver_AppendKeyEvent( 0x7B ); 323 handled = YES; 324 break; 325 326 case NSUpArrowFunctionKey: 327 ESScreensaver_AppendKeyEvent( 0x7E ); 328 handled = YES; 329 break; 330 331 case NSDownArrowFunctionKey: 332 ESScreensaver_AppendKeyEvent( 0x7D ); 333 handled = YES; 334 break; 335 336 case NSF1FunctionKey: 337 ESScreensaver_AppendKeyEvent( 0x7A ); 338 handled = YES; 339 break; 340 341 case NSF2FunctionKey: 342 ESScreensaver_AppendKeyEvent( 0x78 ); 343 handled = YES; 344 break; 345 346 case NSF3FunctionKey: 347 ESScreensaver_AppendKeyEvent( 0x63 ); 348 handled = YES; 349 break; 350 351 case NSF4FunctionKey: 352 ESScreensaver_AppendKeyEvent( 0x76 ); 353 handled = YES; 354 break; 355 356 case NSF8FunctionKey: 357 ESScreensaver_AppendKeyEvent( 0x64 ); 358 handled = YES; 359 break; 360 361 default: 362 break; 363 } 364 } 365 366 // If we didn't handle the key press, send it to the parent class 367 if (handled == NO) 368 [super keyDown:ev]; 369} 370 371// Called immediately before relaunching. 372- (void)updaterWillRelaunchApplication:(SUUpdater *) __unused updater 373{ 374 if (m_config != NULL) 375 [NSApp endSheet:[m_config window]]; 376} 377 378- (void)doUpdate:(NSTimer*)timer 379{ 380 SUAppcastItem* update = [timer userInfo]; 381 382 if (!m_isFullScreen) 383 [m_updater checkForUpdatesInBackground]; 384 else 385 ESScreensaver_SetUpdateAvailable([[update displayVersionString] UTF8String]); 386} 387 388// Sent when a valid update is found by the update driver. 389- (void)updater:(SUUpdater *) __unused updater didFindValidUpdate:(SUAppcastItem *)update 390{ 391 [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(doUpdate:) userInfo:update repeats:NO]; 392} 393 394- (BOOL)fullscreen 395{ 396 return m_isFullScreen; 397} 398 399- (void)setFullScreen:(BOOL)fullscreen 400{ 401 m_isFullScreen = fullscreen; 402} 403 404 405@end 406