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);
79 // [self setBounds:NSMakeRect(0, 0, 640, 480)];
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];
135 glBegin(GL_LINE_LOOP);
136 glColor3d(0.7, 0.7, 0.7);
138 glVertex2i(ProjectMovieSize.size.width+1, -1);
139 glVertex2i(ProjectMovieSize.size.width+1, ProjectMovieSize.size.height+1);
140 glVertex2i(-1, ProjectMovieSize.size.height+1);
145 memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
146 for(i = 0; i < size; i++)
147 sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
149 for(i = 0; i < TRACK_SIZE; i++){
150 if(sortedLayerSet[i] == 0) continue;
152 ci = [sortedLayerSet[i] getEffectedImageWithoutStamp:time]; // 違いはここ。
153 point = [sortedLayerSet[i] getPositionForTime:[sortedLayerSet[i] convertToInnnerTime:time]];
154 if(ci == nil) continue; // サウンドレイヤーはスキップ
155 imageRect = [ci extent];
156 if(imageRect.size.width >= 4000){
157 imageRect = CGRectMake(0.0, 0.0, 4000, 3000);
160 cp = *(CGPoint*)&point;
161 // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, imageRect.size.width, imageRect.size.height) fromRect:imageRect];
162 [ciContext drawImage:ci atPoint:cp fromRect:imageRect];
163 // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, 640, 480) fromRect:CGRectMake(0, 0, 640, 480)];
169 for(i = 0; i < size; i++)
170 [[layerSet objectAtIndex:i] releaseContext];
172 [layerSet removeAllObjects];
177 - (void)drawRect:(NSRect)rect
181 [[self openGLContext] makeCurrentContext];
182 glClear(GL_COLOR_BUFFER_BIT);
184 int i, size = [layerSet count];
192 glBegin(GL_LINE_LOOP);
193 glColor3d(0.7, 0.7, 0.7);
195 glVertex2i(ProjectMovieSize.size.width+1, -1);
196 glVertex2i(ProjectMovieSize.size.width+1, ProjectMovieSize.size.height+1);
197 glVertex2i(-1, ProjectMovieSize.size.height+1);
202 memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
203 for(i = 0; i < size; i++)
204 sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
206 for(i = 0; i < TRACK_SIZE; i++){
207 if(sortedLayerSet[i] == 0) continue;
209 ci = [sortedLayerSet[i] getEffectedImage:stamp forTime:_qt];
210 point = [sortedLayerSet[i] getPositionForTime:[sortedLayerSet[i] convertToInnnerTime:_qt]];
211 if(ci == nil) continue; // サウンドレイヤーはスキップ
213 imageRect = [ci extent];
214 if(imageRect.size.width >= 4000){
215 imageRect = CGRectMake(0, 0, 4000, 3000);
218 cp = *(CGPoint*)&point;
219 // [ciContext drawImage:ci inRect:imageRect fromRect:CGRectMake(point.x, point.y, ProjectMovieSize.size.width, ProjectMovieSize.size.height)];
220 [ciContext drawImage:ci atPoint:cp fromRect:imageRect];
221 // [ciContext drawImage:ci inRect:CGRectMake(point.x, point.y, imageRect.size.width, imageRect.size.height)
222 // fromRect:imageRect];
228 for(i = 0; i < size; i++)
229 [[layerSet objectAtIndex:i] releaseContext];
231 [layerSet removeAllObjects];
238 GLfloat minX, minY, maxX, maxY;
240 NSRect sceneBounds = [self bounds];
241 NSRect frame = [self frame];
243 minX = NSMinX(sceneBounds);
244 minY = NSMinY(sceneBounds);
245 maxX = NSMaxX(sceneBounds);
246 maxY = NSMaxY(sceneBounds);
249 // glViewport(0, 0, (GLsizei)ProjectMovieSize.size.width, (GLsizei)ProjectMovieSize.size.height);
251 glViewport(0, 0, (GLsizei)frame.size.width, (GLsizei)frame.size.height); // set the viewport
253 glMatrixMode(GL_MODELVIEW); // select the modelview matrix
254 glLoadIdentity(); // reset it
256 glMatrixMode(GL_PROJECTION); // select the projection matrix
257 glLoadIdentity(); // reset it
260 // gluOrtho2D(minX, minX + ProjectMovieSize.size.width, minY, minY + ProjectMovieSize.size.height);
262 gluOrtho2D(minX, maxX, minY, maxY); // define a 2-D orthographic projection matrix
265 // if(frame.size.height < frame.size.width)
266 // scale = frame.size.height/ProjectMovieSize.size.height;
268 // scale = frame.size.width/ProjectMovieSize.size.width;
270 // glScalef(scale, scale, 1.0);
272 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
277 - (void)stopDisplayLink
281 CVDisplayLinkStop(displayLink);
284 - (void)startDisplayLink
286 startTime = [[NSDate alloc] init];
287 CVDisplayLinkStart(displayLink);
290 - (void)seek:(QTTime)time
295 - (void)getCurrentPixelData:(NSRect)rect buffer:(void*)buffer
297 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
298 glPixelStorei(GL_PACK_ALIGNMENT, 4);
299 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
300 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
301 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
303 // glReadBuffer(GL_FRONT); // フロントバッファ(って何だろう?)からピクセルを読みに行く。
304 glReadPixels(0, 0, rect.size.width, rect.size.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);