OSDN Git Service

open
[eliscolors/main.git] / ElisMainView.m
1 //  Copyright (c) 2009 Yanagi Asakura
2 //
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.
6 //
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:
10 //
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.
15 //
16 //  2. Altered source versions must be plainly marked as such, and must not be
17 //  misrepresented as being the original software.
18 //
19 //  3. This notice may not be removed or altered from any source
20 //  distribution.
21
22 //
23 //  ElisMainView.m
24 //  Elis Colors
25 //
26 //  Created by 柳 on 09/09/12.
27 //  Copyright 2009 __MyCompanyName__. All rights reserved.
28 //
29
30 #import "ElisMainView.h"
31
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)
39 {
40         return [(ElisMainView *)displayLinkContext getFrameForTime:inOutputTime flagsOut:flagsOut];
41 }
42
43 @implementation ElisMainView
44
45 - (void)awakeFromNib
46 {
47     mainView = self;
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;
54     rendering = NO;
55 }
56
57 - (void)prepareOpenGL
58 {
59     NSLog(@"Initializing OpenGL ...");
60         GLint swapInterval = 1;
61     
62     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);   // black background
63         [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
64     
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]];
70     
71     CGColorSpaceRelease(colorSpace);
72     
73     CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &displayLink);
74     if (NULL != displayLink) {
75         CVDisplayLinkSetCurrentCGDisplay(displayLink, kCGDirectMainDisplay);
76         CVDisplayLinkSetOutputCallback(displayLink, &MyRenderCallback, self);
77     }
78     
79     scale = 1.0;
80 //    [self setFrame:NSMakeRect(0, 0, 640/2, 480/2)];
81     
82     NSLog(@"Elis Colors, Stand by ready.");
83 }
84
85 #pragma mark Display Link
86 - (CVReturn)getFrameForTime:(CVTimeStamp*)timeStamp flagsOut:(CVOptionFlags*)flagsOut
87 {
88     QTTime qt;
89     NSDate* now;
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); // オフセットを足す。
95     
96     stamp = timeStamp;
97
98     [layerSet removeAllObjects];
99     [_mainController getFrameForTime:_qt result:layerSet];
100     [self drawRect:NSZeroRect];
101
102 //    int i, size = [layerSet count];
103 //    for(i = 0; i < size; i++)
104 //        [[layerSet objectAtIndex:i] releaseContext];
105
106     return kCVReturnSuccess;
107 }
108
109 - (void)getFrameForQTTime:(QTTime)time
110 {
111     [layerSet removeAllObjects];
112     [_mainController getFrameForTime:time result:layerSet];
113     [self drawRectWithoutStamp:NSZeroRect forTime:time];
114     
115 //    int i, size = [layerSet count];
116 //    for(i = 0; i < size; i++)
117 //        [[layerSet objectAtIndex:i] releaseContext];
118 }
119
120 - (void)drawRectWithoutStamp:(NSRect)rect forTime:(QTTime)time
121 {
122     [lock lock];
123     
124     [[self openGLContext] makeCurrentContext];
125     glClear(GL_COLOR_BUFFER_BIT);
126     
127     int i, size = [layerSet count];
128     CIImage* ci;
129     NSPoint point;
130     CGRect imageRect;
131     CGPoint cp;
132     NSRect frame = [self frame];
133     NSSize originSize;
134     float dx, dy;
135     
136     dx = (frame.size.width - ProjectMovieSize.size.width)/2;
137     dy = (frame.size.height - ProjectMovieSize.size.height)/2;
138
139     // トラック番号順にバケットソート
140     memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
141     for(i = 0; i < size; i++)
142         sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
143     
144     for(i = 0; i < TRACK_SIZE; i++){
145         if(sortedLayerSet[i] == 0) continue;
146         
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);
154         }
155         
156         cp = *(CGPoint*)&point;
157         if(rendering == NO){
158             cp.x += dx;
159             cp.y += dy;
160         }
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)];
166     }
167     
168     // 境界線を引く
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);
176         glEnd();
177     }
178     
179     glFlush();
180     
181     // あとかたづけ
182     for(i = 0; i < size; i++)
183         [[layerSet objectAtIndex:i] releaseContext];
184     
185     [layerSet removeAllObjects];
186
187     [lock unlock];
188 }
189
190 - (void)drawRect:(NSRect)rect
191 {
192     [lock lock];
193     
194     [[self openGLContext] makeCurrentContext];
195     glClear(GL_COLOR_BUFFER_BIT);
196
197     int i, size = [layerSet count];
198     CIImage* ci;
199     NSPoint point;
200     CGRect imageRect;
201     CGPoint cp;
202     NSRect frame = [self frame];
203     NSSize originSize;
204     float dx, dy;
205     
206     dx = (frame.size.width - ProjectMovieSize.size.width)/2;
207     dy = (frame.size.height - ProjectMovieSize.size.height)/2;
208     
209     // トラック番号順にバケットソート
210     memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
211     for(i = 0; i < size; i++)
212         sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
213
214     for(i = 0; i < TRACK_SIZE; i++){
215         if(sortedLayerSet[i] == 0) continue;
216         
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; // サウンドレイヤーはスキップ
221         
222         imageRect = [ci extent];
223         if(imageRect.size.width >= 4000){
224             imageRect = CGRectMake(0, 0, 4000, 3000);
225         }
226
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];
234     }
235     
236     // 境界線を引く
237     if(printBorderLine){
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);
244         glEnd();
245     }
246     
247     glFlush();
248     
249     // あとかたづけ
250     for(i = 0; i < size; i++)
251         [[layerSet objectAtIndex:i] releaseContext];
252     
253     [layerSet removeAllObjects];
254     
255     [lock unlock];
256 }
257
258 - (void)reshape
259
260         GLfloat minX, minY, maxX, maxY;
261     
262     NSRect sceneBounds = [self bounds];
263         NSRect frame = [self frame];
264         
265     minX = NSMinX(sceneBounds);
266         minY = NSMinY(sceneBounds);
267         maxX = NSMaxX(sceneBounds);
268         maxY = NSMaxY(sceneBounds);
269     
270 //    if(rendering)
271 //        glViewport(0, 0, (GLsizei)ProjectMovieSize.size.width, (GLsizei)ProjectMovieSize.size.height);
272 //    else
273         glViewport(0, 0, (GLsizei)frame.size.width, (GLsizei)frame.size.height);        // set the viewport
274     
275     glMatrixMode(GL_MODELVIEW);    // select the modelview matrix
276     glLoadIdentity();              // reset it
277     
278     glMatrixMode(GL_PROJECTION);   // select the projection matrix
279     glLoadIdentity();              // reset it
280     
281 //    if(rendering)
282 //        gluOrtho2D(minX, minX + ProjectMovieSize.size.width, minY, minY + ProjectMovieSize.size.height);
283 //    else
284         gluOrtho2D(minX, maxX, minY, maxY);     // define a 2-D orthographic projection matrix
285     
286 //    float scale;
287 //    if(frame.size.height < frame.size.width)
288 //        scale = frame.size.height/ProjectMovieSize.size.height;
289 //    else 
290 //        scale = frame.size.width/ProjectMovieSize.size.width;
291     
292 //    glScalef(scale, scale, 1.0);
293     
294         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
295     glEnable(GL_BLEND);
296
297 }
298
299 - (void)stopDisplayLink
300 {
301     [startTime release];
302     startTime = nil;
303     CVDisplayLinkStop(displayLink);
304 }
305
306 - (void)startDisplayLink
307 {
308     startTime = [[NSDate alloc] init];
309     CVDisplayLinkStart(displayLink);
310 }
311
312 - (void)seek:(QTTime)time
313 {
314     timeOffset = time;
315 }
316
317 - (void)getCurrentPixelData:(NSRect)rect buffer:(void*)buffer
318 {    
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);
324     
325     // これが公式の方法とかマジないわー。
326     glReadPixels(0, 0, rect.size.width, rect.size.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
327     
328     glPopClientAttrib();
329 }
330
331 @end