// // ElisMainView.m // Elis Colors // // Created by 柳 on 09/09/12. // Copyright 2009 __MyCompanyName__. All rights reserved. // #import "ElisMainView.h" #pragma mark Render Callback static CVReturn MyRenderCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) { return [(ElisMainView *)displayLinkContext getFrameForTime:inOutputTime flagsOut:flagsOut]; } @implementation ElisMainView - (void)awakeFromNib { mainView = self; lock = [[NSRecursiveLock alloc] init]; timeOffset = QTZeroTime; // layerSet = malloc(sizeof(void*) * TRACK_SIZE); layerSet = [[NSMutableArray alloc] init]; sortedLayerSet = malloc(sizeof(void*) * TRACK_SIZE); } - (void)prepareOpenGL { NSLog(@"Initializing OpenGL ..."); GLint swapInterval = 1; glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // black background [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); ciContext = [CIContext contextWithCGLContext:[[self openGLContext] CGLContextObj] pixelFormat:[[self pixelFormat] CGLPixelFormatObj] options:[NSDictionary dictionaryWithObjectsAndKeys:(id)colorSpace, kCIContextOutputColorSpace, (id)colorSpace, kCIContextWorkingColorSpace, nil]]; CGColorSpaceRelease(colorSpace); CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &displayLink); if (NULL != displayLink) { CVDisplayLinkSetCurrentCGDisplay(displayLink, kCGDirectMainDisplay); CVDisplayLinkSetOutputCallback(displayLink, &MyRenderCallback, self); } NSLog(@"Elis Colors, Stand by ready."); } #pragma mark Display Link - (CVReturn)getFrameForTime:(CVTimeStamp*)timeStamp flagsOut:(CVOptionFlags*)flagsOut { [lock lock]; QTTime qt; NSDate* now; NSTimeInterval duration; now = [[NSDate alloc] init]; duration = [now timeIntervalSinceDate:startTime]; // 再生を開始した時間と今の時間から経過時間を得る。 qt = QTMakeTime(duration*600, 600); // 経過時間をQTTimeに変換。 _qt = QTTimeIncrement(qt, timeOffset); // オフセットを足す。 stamp = timeStamp; // [layerSet removeAllObjects]; [_mainController getFrameForTime:_qt result:layerSet]; // [now release]; [self drawRect:NSZeroRect]; [lock unlock]; return kCVReturnSuccess; } - (void)getFrameForQTTime:(QTTime)time { [lock lock]; [layerSet removeAllObjects]; [_mainController getFrameForTime:time result:layerSet]; [self drawRectWithoutStamp:NSZeroRect forTime:time]; [lock unlock]; } - (void)drawRectWithoutStamp:(NSRect)rect forTime:(QTTime)time { [lock lock]; [[self openGLContext] makeCurrentContext]; glClear(GL_COLOR_BUFFER_BIT); int i, size = [layerSet count]; CIImage* ci; NSPoint point; CGRect imageRect; CGPoint cp; // トラック番号順にバケットソート memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE); for(i = 0; i < size; i++) sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i]; for(i = 0; i < TRACK_SIZE; i++){ if(sortedLayerSet[i] == 0) continue; ci = [sortedLayerSet[i] getEffectedImageWithoutStamp:time]; // 違いはここ。 point = [sortedLayerSet[i] getPositionForTime:[sortedLayerSet[i] convertToInnnerTime:time]]; if(ci == nil) continue; // サウンドレイヤーはスキップ imageRect = [ci extent]; if(imageRect.size.width >= 4000){ imageRect = CGRectMake(0.0, 0.0, 4000, 3000); } cp = *(CGPoint*)&point; // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, imageRect.size.width, imageRect.size.height) fromRect:imageRect]; [ciContext drawImage:ci atPoint:cp fromRect:imageRect]; // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, 640, 480) fromRect:CGRectMake(0, 0, 640, 480)]; } glFlush(); // あとかたづけ for(i = 0; i < size; i++) [[layerSet objectAtIndex:i] releaseContext]; [layerSet removeAllObjects]; [lock unlock]; } - (void)drawRect:(NSRect)rect { [lock lock]; [[self openGLContext] makeCurrentContext]; glClear(GL_COLOR_BUFFER_BIT); int i, size = [layerSet count]; CIImage* ci; NSPoint point; CGRect imageRect; CGPoint cp; // トラック番号順にバケットソート memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE); for(i = 0; i < size; i++) sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i]; for(i = 0; i < TRACK_SIZE; i++){ if(sortedLayerSet[i] == 0) continue; ci = [sortedLayerSet[i] getEffectedImage:stamp forTime:_qt]; point = [sortedLayerSet[i] getPositionForTime:[sortedLayerSet[i] convertToInnnerTime:_qt]]; if(ci == nil) continue; // サウンドレイヤーはスキップ imageRect = [ci extent]; if(imageRect.size.width >= 4000){ imageRect = CGRectMake(0, 0, 4000, 3000); } cp = *(CGPoint*)&point; // [ciContext drawImage:ci inRect:imageRect fromRect:CGRectMake(point.x, point.y, ProjectMovieSize.size.width, ProjectMovieSize.size.height)]; [ciContext drawImage:ci atPoint:cp fromRect:imageRect]; // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, imageRect.size.width, imageRect.size.height) // fromRect:imageRect]; } // あとかたづけ for(i = 0; i < size; i++) [[layerSet objectAtIndex:i] releaseContext]; [layerSet removeAllObjects]; // int size = [imageSet count], i; // NSPoint np; // CIImage* ci; // CGRect imRect; // for(i = 0; i < size; i += 2){ // ci = [imageSet objectAtIndex:i]; // np = [[imageSet objectAtIndex:i+1] pointValue]; // imRect = [ci extent]; // // if(imRect.size.width >= 4096.0) // imRect = CGRectMake(0, 0, 640, 480); // [ciContext drawImage:ci inRect:imRect//CGRectMake(np.x, np.y, 640, 480) // fromRect:CGRectMake(np.x, np.y, 640, 480)]; // } glFlush(); // size = [contexts count]; // for(i = 0; i < size; i++) // QTVisualContextTask([contexts objectAtIndex:i]); // // [imageSet release]; // imageSet = nil; [lock unlock]; } - (void)reshape { GLfloat minX, minY, maxX, maxY; NSRect sceneBounds = [self bounds]; NSRect frame = [self frame]; minX = NSMinX(sceneBounds); minY = NSMinY(sceneBounds); maxX = NSMaxX(sceneBounds); maxY = NSMaxY(sceneBounds); glViewport(0, 0, (GLsizei)frame.size.width, (GLsizei)frame.size.height); // set the viewport glMatrixMode(GL_MODELVIEW); // select the modelview matrix glLoadIdentity(); // reset it glMatrixMode(GL_PROJECTION); // select the projection matrix glLoadIdentity(); // reset it gluOrtho2D(minX, maxX, minY, maxY); // define a 2-D orthographic projection matrix glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } - (void)stopDisplayLink { [startTime release]; startTime = nil; CVDisplayLinkStop(displayLink); } - (void)startDisplayLink { startTime = [[NSDate alloc] init]; CVDisplayLinkStart(displayLink); } - (void)seek:(QTTime)time { timeOffset = time; } - (void)getCurrentPixelData:(NSRect)rect buffer:(unsigned char*)buffer { glReadBuffer(GL_FRONT); // フロントバッファ(って何だろう?)からピクセルを読みに行く。 glReadPixels(0, 0, rect.size.width, rect.size.height, GL_RGB, GL_UNSIGNED_BYTE, buffer); } @end