1 // Copyright (c) 2009 Yanagi Asakura
3 // This software is provided 'as-is', without any express or implied
4 // warranty. In no event will the authors be held liable for any damages
5 // arising from the use of this software.
7 // Permission is granted to anyone to use this software for any purpose,
8 // including commercial applications, and to alter it and redistribute it
9 // freely, subject to the following restrictions:
11 // 1. The origin of this software must not be misrepresented; you must not
12 // claim that you wrote the original software. If you use this software
13 // in a product, an acknowledgment in the product documentation would be
14 // appreciated but is not required.
16 // 2. Altered source versions must be plainly marked as such, and must not be
17 // misrepresented as being the original software.
19 // 3. This notice may not be removed or altered from any source
26 // Created by 柳 on 09/09/12.
27 // Copyright 2009 __MyCompanyName__. All rights reserved.
30 #import "ElisMainView.h"
32 #pragma mark Render Callback
33 static CVReturn MyRenderCallback(CVDisplayLinkRef displayLink,
34 const CVTimeStamp *inNow,
35 const CVTimeStamp *inOutputTime,
36 CVOptionFlags flagsIn,
37 CVOptionFlags *flagsOut,
38 void *displayLinkContext)
40 return [(ElisMainView *)displayLinkContext getFrameForTime:inOutputTime flagsOut:flagsOut];
43 @implementation ElisMainView
48 lock = [[NSRecursiveLock alloc] init];
49 timeOffset = QTZeroTime;
50 // layerSet = malloc(sizeof(void*) * TRACK_SIZE);
51 layerSet = [[NSMutableArray alloc] init];
52 sortedLayerSet = malloc(sizeof(void*) * TRACK_SIZE);
53 printBorderLine = YES;
59 NSLog(@"Initializing OpenGL ...");
60 GLint swapInterval = 1;
62 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // black background
63 [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
65 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
66 ciContext = [CIContext contextWithCGLContext:[[self openGLContext] CGLContextObj]
67 pixelFormat:[[self pixelFormat] CGLPixelFormatObj]
68 options:[NSDictionary dictionaryWithObjectsAndKeys:(id)colorSpace, kCIContextOutputColorSpace,
69 (id)colorSpace, kCIContextWorkingColorSpace, nil]];
71 CGColorSpaceRelease(colorSpace);
73 CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &displayLink);
74 if (NULL != displayLink) {
75 CVDisplayLinkSetCurrentCGDisplay(displayLink, kCGDirectMainDisplay);
76 CVDisplayLinkSetOutputCallback(displayLink, &MyRenderCallback, self);
80 // [self setFrame:NSMakeRect(0, 0, 640/2, 480/2)];
82 NSLog(@"Elis Colors, Stand by ready.");
85 #pragma mark Display Link
86 - (CVReturn)getFrameForTime:(CVTimeStamp*)timeStamp flagsOut:(CVOptionFlags*)flagsOut
90 NSTimeInterval duration;
91 now = [[NSDate alloc] init];
92 duration = [now timeIntervalSinceDate:startTime]; // 再生を開始した時間と今の時間から経過時間を得る。
93 qt = QTMakeTime(duration*600, 600); // 経過時間をQTTimeに変換。
94 _qt = QTTimeIncrement(qt, timeOffset); // オフセットを足す。
98 [layerSet removeAllObjects];
99 [_mainController getFrameForTime:_qt result:layerSet];
100 [self drawRect:NSZeroRect];
102 // int i, size = [layerSet count];
103 // for(i = 0; i < size; i++)
104 // [[layerSet objectAtIndex:i] releaseContext];
106 return kCVReturnSuccess;
109 - (void)getFrameForQTTime:(QTTime)time
111 [layerSet removeAllObjects];
112 [_mainController getFrameForTime:time result:layerSet];
113 [self drawRectWithoutStamp:NSZeroRect forTime:time];
115 // int i, size = [layerSet count];
116 // for(i = 0; i < size; i++)
117 // [[layerSet objectAtIndex:i] releaseContext];
120 - (void)drawRectWithoutStamp:(NSRect)rect forTime:(QTTime)time
124 [[self openGLContext] makeCurrentContext];
125 glClear(GL_COLOR_BUFFER_BIT);
127 int i, size = [layerSet count];
132 NSRect frame = [self frame];
136 dx = (frame.size.width - ProjectMovieSize.size.width)/2;
137 dy = (frame.size.height - ProjectMovieSize.size.height)/2;
140 memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
141 for(i = 0; i < size; i++)
142 sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
144 for(i = 0; i < TRACK_SIZE; i++){
145 if(sortedLayerSet[i] == 0) continue;
147 ci = [sortedLayerSet[i] getEffectedImageWithoutStamp:time]; // 違いはここ。
148 point = [sortedLayerSet[i] getPositionForTime:[sortedLayerSet[i] convertToInnnerTime:time]];
149 originSize = [sortedLayerSet[i] originSize];
150 if(ci == nil) continue; // サウンドレイヤーはスキップ
151 imageRect = [ci extent];
152 if(imageRect.size.width >= 4000){
153 imageRect = CGRectMake(0.0, 0.0, 4000, 3000);
156 cp = *(CGPoint*)&point;
161 cp.x -= (imageRect.size.width - originSize.width)/2;
162 cp.y -= (imageRect.size.height - originSize.height)/2;
163 // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, imageRect.size.width, imageRect.size.height) fromRect:imageRect];
164 [ciContext drawImage:ci atPoint:cp fromRect:imageRect];
165 // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, 640, 480) fromRect:CGRectMake(0, 0, 640, 480)];
169 if(printBorderLine && rendering == NO){
170 glBegin(GL_LINE_LOOP);
171 glColor3d(0.7, 0.7, 0.7);
172 glVertex2i(dx+1, dy+1);
173 glVertex2i(ProjectMovieSize.size.width+1+dx, dy+1);
174 glVertex2i(ProjectMovieSize.size.width+1+dx, ProjectMovieSize.size.height+1+dy);
175 glVertex2i(dx+1, ProjectMovieSize.size.height+1+dy);
182 for(i = 0; i < size; i++)
183 [[layerSet objectAtIndex:i] releaseContext];
185 [layerSet removeAllObjects];
190 - (void)drawRect:(NSRect)rect
194 [[self openGLContext] makeCurrentContext];
195 glClear(GL_COLOR_BUFFER_BIT);
197 int i, size = [layerSet count];
202 NSRect frame = [self frame];
206 dx = (frame.size.width - ProjectMovieSize.size.width)/2;
207 dy = (frame.size.height - ProjectMovieSize.size.height)/2;
210 memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
211 for(i = 0; i < size; i++)
212 sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
214 for(i = 0; i < TRACK_SIZE; i++){
215 if(sortedLayerSet[i] == 0) continue;
217 ci = [sortedLayerSet[i] getEffectedImage:stamp forTime:_qt];
218 point = [sortedLayerSet[i] getPositionForTime:[sortedLayerSet[i] convertToInnnerTime:_qt]];
219 originSize = [sortedLayerSet[i] originSize];
220 if(ci == nil) continue; // サウンドレイヤーはスキップ
222 imageRect = [ci extent];
223 if(imageRect.size.width >= 4000){
224 imageRect = CGRectMake(0, 0, 4000, 3000);
227 cp = *(CGPoint*)&point;
228 cp.x += dx - (imageRect.size.width - originSize.width)/2;
229 cp.y += dy - (imageRect.size.height - originSize.height)/2;
230 // [ciContext drawImage:ci inRect:imageRect fromRect:CGRectMake(point.x, point.y, ProjectMovieSize.size.width, ProjectMovieSize.size.height)];
231 [ciContext drawImage:ci atPoint:cp fromRect:imageRect];
232 // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, imageRect.size.width, imageRect.size.height)
233 // fromRect:imageRect];
238 glBegin(GL_LINE_LOOP);
239 glColor3d(0.7, 0.7, 0.7);
240 glVertex2i(dx+1, dy+1);
241 glVertex2i(ProjectMovieSize.size.width+1+dx, dy+1);
242 glVertex2i(ProjectMovieSize.size.width+1+dx, ProjectMovieSize.size.height+1+dy);
243 glVertex2i(dx+1, ProjectMovieSize.size.height+1+dy);
250 for(i = 0; i < size; i++)
251 [[layerSet objectAtIndex:i] releaseContext];
253 [layerSet removeAllObjects];
260 GLfloat minX, minY, maxX, maxY;
262 NSRect sceneBounds = [self bounds];
263 NSRect frame = [self frame];
265 minX = NSMinX(sceneBounds);
266 minY = NSMinY(sceneBounds);
267 maxX = NSMaxX(sceneBounds);
268 maxY = NSMaxY(sceneBounds);
271 // glViewport(0, 0, (GLsizei)ProjectMovieSize.size.width, (GLsizei)ProjectMovieSize.size.height);
273 glViewport(0, 0, (GLsizei)frame.size.width, (GLsizei)frame.size.height); // set the viewport
275 glMatrixMode(GL_MODELVIEW); // select the modelview matrix
276 glLoadIdentity(); // reset it
278 glMatrixMode(GL_PROJECTION); // select the projection matrix
279 glLoadIdentity(); // reset it
282 // gluOrtho2D(minX, minX + ProjectMovieSize.size.width, minY, minY + ProjectMovieSize.size.height);
284 gluOrtho2D(minX, maxX, minY, maxY); // define a 2-D orthographic projection matrix
287 // if(frame.size.height < frame.size.width)
288 // scale = frame.size.height/ProjectMovieSize.size.height;
290 // scale = frame.size.width/ProjectMovieSize.size.width;
292 // glScalef(scale, scale, 1.0);
294 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
299 - (void)stopDisplayLink
303 CVDisplayLinkStop(displayLink);
306 - (void)startDisplayLink
308 startTime = [[NSDate alloc] init];
309 CVDisplayLinkStart(displayLink);
312 - (void)seek:(QTTime)time
317 - (void)getCurrentPixelData:(NSRect)rect buffer:(void*)buffer
319 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
320 glPixelStorei(GL_PACK_ALIGNMENT, 4);
321 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
322 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
323 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
326 glReadPixels(0, 0, rect.size.width, rect.size.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);