PageRenderTime 99ms CodeModel.GetById 6ms app.highlight 87ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/visualizations/Goom/goom2k4-0/mac/StandAlone/AppController.m

http://github.com/xbmc/xbmc
Objective C | 438 lines | 286 code | 69 blank | 83 comment | 35 complexity | 43f362eca6efa14929fec14a8b182c20 MD5 | raw file
  1#import "AppController.h"
  2#import "GoomFXView.h"
  3#include "src/goom.h"
  4
  5#import <OpenGL/OpenGL.h>
  6
  7@interface AppController (AnimationMethods)
  8- (BOOL) isAnimating;
  9- (void) startAnimation;
 10- (void) stopAnimation;
 11- (void) toggleAnimation;
 12
 13- (void) startAnimationTimer;
 14- (void) stopAnimationTimer;
 15- (void) animationTimerFired:(NSTimer *)timer;
 16@end
 17
 18static float HowLong(AbsoluteTime * backUpTime)
 19{
 20    AbsoluteTime absTime;
 21    Nanoseconds nanosec;
 22    
 23    absTime = SubAbsoluteFromAbsolute(UpTime(), *backUpTime);
 24    nanosec = AbsoluteToNanoseconds(absTime);
 25    //fprintf(stderr,"Time :  %f\n", (float) UnsignedWideToUInt64( nanosec ) / 1000000000.0);
 26    //fprintf(stderr,"FPS :  %f\n", (float) 1000000000.0f/UnsignedWideToUInt64( nanosec ));
 27    *backUpTime = UpTime();
 28    return (float) (1000000000.0f/UnsignedWideToUInt64( nanosec ));
 29}
 30
 31static void logGLError(int line)
 32{
 33    GLenum err = glGetError();
 34    char * code;
 35    
 36    if (err == GL_NO_ERROR) return;
 37    
 38    switch (err)
 39    {
 40        case GL_INVALID_ENUM:
 41            code = "GL_INVALID_ENUM";
 42            break;
 43        case GL_INVALID_VALUE:
 44            code = "GL_INVALID_VALUE";
 45            break;
 46        case GL_INVALID_OPERATION:
 47            code = "GL_INVALID_OPERATION";
 48            break;
 49        case GL_STACK_OVERFLOW:
 50            code = "GL_STACK_OVERFLOW";
 51            break;
 52        case GL_STACK_UNDERFLOW:
 53            code = "GL_STACK_UNDERFLOW";
 54            break;
 55        case GL_OUT_OF_MEMORY:
 56            code = "GL_OUT_OF_MEMORY";
 57            break;
 58        default:
 59            code = "Unknown Error";
 60            break;
 61    }
 62    fprintf(stderr,"iGoom OpenGL error : %s", code);
 63    
 64}
 65
 66@implementation AppController
 67
 68-(void) awakeFromNib
 69{
 70    PluginInfo * goomInfos;
 71    int i;
 72    
 73    goomInfos = [myGoom infos];
 74    
 75    for (i=0; i < goomInfos->nbParams; i++)
 76    {
 77        NSTabViewItem * item = [[[NSTabViewItem alloc] initWithIdentifier:nil] autorelease];
 78        [item setLabel:[NSString stringWithCString:goomInfos->params[i].name]];
 79        [item setView:[[[GoomFXView alloc] initWithFrame:[TabView contentRect] andFX:goomInfos->params[i]] autorelease]];
 80        [TabView addTabViewItem:item];
 81        
 82        // Create and load textures for the first time
 83        //[GLView loadTextures:GL_TRUE];
 84    }
 85
 86    //[self goFullScreen:self];
 87    isAnimating = NO;
 88    lastFPS = 0.0f;
 89    backUpTime=UpTime();
 90    FrameRate = 0.028f; // ~35 FPS
 91    
 92    if ([GLView canBeHQ])
 93    {
 94        [HQButton setEnabled:YES];
 95        [QEWarning removeFromSuperview];
 96    }
 97    
 98    [self startAnimation];
 99}
100
101
102// Action method wired up to fire when the user clicks the "Go FullScreen" button.  We remain in this method until the user exits FullScreen mode.
103- (IBAction) goFullScreen:(id)sender
104{
105    CFAbsoluteTime timeNow;
106    CGLContextObj cglContext;
107    CGDisplayErr err;
108    long oldSwapInterval;
109    long newSwapInterval;
110    BOOL plugrunning = YES;
111    long rendererID;
112
113    // Pixel Format Attributes for the FullScreen NSOpenGLContext
114    NSOpenGLPixelFormatAttribute attrs[] = {
115
116        // Specify that we want a full-screen OpenGL context.
117        NSOpenGLPFAFullScreen,
118
119        // We may be on a multi-display system (and each screen may be driven by a different renderer),
120        // so we need to specify which screen we want to take over.
121        // For this demo, we'll specify the main screen.
122        NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
123
124        // Attributes Common to FullScreen and non-FullScreen
125        NSOpenGLPFAColorSize, 24,
126        NSOpenGLPFADepthSize, 16,
127        NSOpenGLPFADoubleBuffer,
128        NSOpenGLPFAAccelerated,
129        0
130    };
131
132    // Create the FullScreen NSOpenGLContext with the attributes listed above.
133    NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];    
134    if (pixelFormat == nil) {
135        NSLog(@"Failed to create 1st pixelFormat, trying another format...");
136        NSOpenGLPixelFormatAttribute attrs2[] = {
137            NSOpenGLPFAFullScreen,
138            NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
139            0
140        };
141        
142        // Create the FullScreen NSOpenGLContext with the attributes listed above.
143        NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs2];    
144        if (pixelFormat == nil) {
145            NSLog(@"Failed to create 2nd pixelFormat, canceling full screen mode.");
146            return;
147        }
148    }
149    
150    // Just as a diagnostic, report the renderer ID that this pixel format binds to.
151    // CGLRenderers.h contains a list of known renderers and their corresponding RendererID codes.
152    [pixelFormat getValues:&rendererID forAttribute:NSOpenGLPFARendererID forVirtualScreen:0];
153    
154    // Create an NSOpenGLContext with the FullScreen pixel format.
155    // By specifying the non-FullScreen context as our "shareContext",
156    // we automatically inherit all of the textures, display lists, and other OpenGL objects it has defined.
157    fullScreenContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:[GLView openGLContext]];
158    [pixelFormat release];
159    pixelFormat = nil;
160    
161    if (fullScreenContext == nil) {
162        NSLog(@"Failed to create fullScreenContext");
163        return;
164    }
165    
166    // Pause animation in the OpenGL view.
167    // While we're in full-screen mode, we'll drive the animation actively instead of using a timer callback.
168    if ([self isAnimating]) {
169        [self stopAnimationTimer];
170    }
171
172    // Take control of the display where we're about to go FullScreen.
173    err = CGCaptureAllDisplays();
174    if (err != CGDisplayNoErr) {
175        [fullScreenContext release];
176        fullScreenContext = nil;
177        return;
178    }
179
180    // Enter FullScreen mode and make our FullScreen context the active context for OpenGL commands.
181    [fullScreenContext setFullScreen];
182    [fullScreenContext makeCurrentContext];
183
184    // Save the current swap interval so we can restore it later, and then set the new swap interval to lock us to the display's refresh rate.
185    cglContext = CGLGetCurrentContext();
186    CGLGetParameter(cglContext, kCGLCPSwapInterval, &oldSwapInterval);
187    newSwapInterval = 1;
188    CGLSetParameter(cglContext, kCGLCPSwapInterval, &newSwapInterval);
189
190    // Tell the myGoom the dimensions of the area it's going to render to, so it can set up an appropriate viewport and viewing transformation.
191    [myGoom setSize:NSMakeSize(CGDisplayPixelsWide(kCGDirectMainDisplay), CGDisplayPixelsHigh(kCGDirectMainDisplay))];
192
193    // Now that we've got the screen, we enter a loop in which we alternately process input events and computer and render the next frame of our animation.  The shift here is from a model in which we passively receive events handed to us by the AppKit to one in which we are actively driving event processing.
194    timeBefore = CFAbsoluteTimeGetCurrent();
195    stayInFullScreenMode = YES;
196    while (stayInFullScreenMode) {
197        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
198
199        // Check for and process input events.
200        NSEvent *event;
201        while (event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]) {
202            switch ([event type]) {
203                case NSLeftMouseDown:
204                    [self mouseDown:event];
205                    break;
206
207                case NSLeftMouseUp:
208                    plugrunning = plugrunning?NO:YES;
209                    [self mouseUp:event];
210                    break;
211
212                case NSRightMouseUp:
213                    plugrunning = plugrunning?NO:YES;
214                    break;
215                    
216                case NSLeftMouseDragged:
217                    [self mouseDragged:event];
218                    break;
219
220                case NSKeyDown:
221                    [self keyDown:event];
222                    break;
223
224                default:
225                    break;
226            }
227        }
228
229        // Render a frame, and swap the front and back buffers.
230        timeNow = CFAbsoluteTimeGetCurrent();
231        if ((timeNow-timeBefore) >= FrameRate)
232        {
233            timeBefore = timeNow;
234            if (plugrunning==YES) {
235                [myGoom render];
236                [fullScreenContext flushBuffer];
237            }
238        }
239
240
241        // Clean up any autoreleased objects that were created this time through the loop.
242        [pool release];
243    }
244    
245    // Clear the front and back framebuffers before switching out of FullScreen mode.  (This is not strictly necessary, but avoids an untidy flash of garbage.)
246    glClearColor(0.0, 0.0, 0.0, 0.0);
247    glClear(GL_COLOR_BUFFER_BIT);
248    [fullScreenContext flushBuffer];
249    glClear(GL_COLOR_BUFFER_BIT);
250    [fullScreenContext flushBuffer];
251
252    // Restore the previously set swap interval.
253    CGLSetParameter(cglContext, kCGLCPSwapInterval, &oldSwapInterval);
254
255    // Exit fullscreen mode and release our FullScreen NSOpenGLContext.
256    [NSOpenGLContext clearCurrentContext];
257    [fullScreenContext clearDrawable];
258    [fullScreenContext release];
259    fullScreenContext = nil;
260
261    // Release control of the display.
262    CGReleaseAllDisplays();
263
264    // Reset the size to the window size
265    [myGoom setSize:[GLView frame].size];
266    
267    // Mark our view as needing drawing.  (The animation has advanced while we were in FullScreen mode, so its current contents are stale.)
268    [GLView setNeedsDisplay:YES];
269
270    // Resume animation timer firings.
271    if ([self isAnimating]) {
272        [self startAnimationTimer];
273    }
274}
275
276- (IBAction) setHighQuality:(id)sender
277{
278    [myGoom setHighQuality:([sender state]==NSOnState)];
279}
280
281- (IBAction) setFrameRate:(id)sender
282{
283    FrameRate = 1.0f/[sender floatValue];
284    [self stopAnimation];
285    [self startAnimation];
286}
287
288- (void) keyDown:(NSEvent *)event
289{
290    unichar c = [[event charactersIgnoringModifiers] characterAtIndex:0];
291    switch (c) {
292
293        // [Esc] exits FullScreen mode.
294        case 27:
295            stayInFullScreenMode = NO;
296            break;
297
298        // [space] toggles rotation of the globe.
299        case 32:
300            [self toggleAnimation];
301            break;
302
303        case 'l':
304        case 'L':
305            [myGoom setHighQuality:NO];
306            break;
307            
308        case 'h':
309        case 'H':
310            [myGoom setHighQuality:YES];
311            break;
312            
313        default:
314            break;
315    }
316}
317/*
318- (void)mouseDown:(NSEvent *)theEvent
319{
320    BOOL wasAnimating = [self isAnimating];
321    BOOL dragging = YES;
322    NSPoint windowPoint;
323    NSPoint lastWindowPoint = [theEvent locationInWindow];
324    float dx, dy;
325
326    if (wasAnimating) {
327        [self stopAnimation];
328    }
329    while (dragging) {
330        theEvent = [[GLView window] nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask];
331        windowPoint = [theEvent locationInWindow];
332        switch ([theEvent type]) {
333            case NSLeftMouseUp:
334                dragging = NO;
335                break;
336
337            case NSLeftMouseDragged:
338                dx = windowPoint.x - lastWindowPoint.x;
339                dy = windowPoint.y - lastWindowPoint.y;
340                lastWindowPoint = windowPoint;
341
342                // Render a frame.
343                if (fullScreenContext) {
344                    [myGoom render];
345                    [fullScreenContext flushBuffer];
346                } else {
347                    [GLView display];
348                }
349                break;
350
351            default:
352                break;
353        }
354    }
355    if (wasAnimating) {
356        [self startAnimation];
357        timeBefore = CFAbsoluteTimeGetCurrent();
358    }
359}
360*/
361- (BOOL) isInFullScreenMode
362{
363    return fullScreenContext != nil;
364}
365
366@end
367
368@implementation AppController (AnimationMethods)
369
370- (BOOL) isAnimating
371{
372    return isAnimating;
373}
374
375- (void) startAnimation
376{
377    if (!isAnimating) {
378        isAnimating = YES;
379        if (![self isInFullScreenMode])
380        {
381            [self startAnimationTimer];
382        }
383    }
384}
385
386- (void) stopAnimation
387{
388    if (isAnimating) {
389        if (animationTimer != nil) {
390            [self stopAnimationTimer];
391        }
392        isAnimating = NO;
393    }
394}
395
396- (void) toggleAnimation
397{
398    if ([self isAnimating]) [self stopAnimation];
399    else [self startAnimation];
400}
401
402- (void) startAnimationTimer
403{
404    if (animationTimer == nil) {
405        animationTimer = [[NSTimer scheduledTimerWithTimeInterval:FrameRate target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES] retain];
406    }
407}
408
409- (void) stopAnimationTimer
410{
411    if (animationTimer != nil) {
412        [animationTimer invalidate];
413        [animationTimer release];
414        animationTimer = nil;
415    }
416}
417
418- (void) animationTimerFired:(NSTimer *)timer
419{
420    lastFPS = (HowLong(&backUpTime) + lastFPS) * 0.5f;
421    [FPSCounter setStringValue:[NSString stringWithFormat:@"%d/%d FPS",(int)lastFPS,(int)(1.0f/FrameRate)]];
422    [GLView setNeedsDisplay:YES];
423}
424
425// TAB VIEW DELEGATE
426- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem
427{
428    NSRect frame = [PrefWin frame];
429    float height;
430    if(![[tabViewItem identifier] isEqual:@"maintab"]) height = ((GoomFXView*)[tabViewItem view])->height;
431    else height = 356.0f;
432    height += 20.0f;
433    frame.origin.y -= height-frame.size.height;
434    frame.size.height = height;
435    [PrefWin setFrame:frame display:YES animate:YES];
436}
437
438@end