OSDN Git Service

a996671c28645c9f27b7c1b206fd8457f7cc13f7
[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 //    [self setBounds:NSMakeRect(0, 0, 640, 480)];
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     
133     // 境界線を引く
134     if(printBorderLine){
135     glBegin(GL_LINE_LOOP);
136     glColor3d(0.7, 0.7, 0.7);
137     glVertex2i(-1, -1);
138     glVertex2i(ProjectMovieSize.size.width+1, -1);
139     glVertex2i(ProjectMovieSize.size.width+1, ProjectMovieSize.size.height+1);
140     glVertex2i(-1, ProjectMovieSize.size.height+1);
141     glEnd();
142     }
143     
144     // トラック番号順にバケットソート
145     memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
146     for(i = 0; i < size; i++)
147         sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
148     
149     for(i = 0; i < TRACK_SIZE; i++){
150         if(sortedLayerSet[i] == 0) continue;
151         
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);
158         }
159         
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)];
164     }
165     
166     glFlush();
167     
168     // あとかたづけ
169     for(i = 0; i < size; i++)
170         [[layerSet objectAtIndex:i] releaseContext];
171     
172     [layerSet removeAllObjects];
173
174     [lock unlock];
175 }
176
177 - (void)drawRect:(NSRect)rect
178 {
179     [lock lock];
180     
181     [[self openGLContext] makeCurrentContext];
182     glClear(GL_COLOR_BUFFER_BIT);
183
184     int i, size = [layerSet count];
185     CIImage* ci;
186     NSPoint point;
187     CGRect imageRect;
188     CGPoint cp;
189     
190     // 境界線を引く
191     if(printBorderLine){
192     glBegin(GL_LINE_LOOP);
193     glColor3d(0.7, 0.7, 0.7);
194     glVertex2i(-1, -1);
195     glVertex2i(ProjectMovieSize.size.width+1, -1);
196     glVertex2i(ProjectMovieSize.size.width+1, ProjectMovieSize.size.height+1);
197     glVertex2i(-1, ProjectMovieSize.size.height+1);
198     glEnd();
199     }
200     
201     // トラック番号順にバケットソート
202     memset(sortedLayerSet, 0, sizeof(void*) * TRACK_SIZE);
203     for(i = 0; i < size; i++)
204         sortedLayerSet[[[layerSet objectAtIndex:i] trackNumber]] = [layerSet objectAtIndex:i];
205
206     for(i = 0; i < TRACK_SIZE; i++){
207         if(sortedLayerSet[i] == 0) continue;
208         
209         ci = [sortedLayerSet[i] getEffectedImage:stamp forTime:_qt];
210         point = [sortedLayerSet[i] getPositionForTime:[sortedLayerSet[i] convertToInnnerTime:_qt]];
211         if(ci == nil) continue; // サウンドレイヤーはスキップ
212         
213         imageRect = [ci extent];
214         if(imageRect.size.width >= 4000){
215             imageRect = CGRectMake(0, 0, 4000, 3000);
216         }
217
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];
223     }
224     
225     glFlush();
226     
227     // あとかたづけ
228     for(i = 0; i < size; i++)
229         [[layerSet objectAtIndex:i] releaseContext];
230     
231     [layerSet removeAllObjects];
232     
233     [lock unlock];
234 }
235
236 - (void)reshape
237
238         GLfloat minX, minY, maxX, maxY;
239     
240     NSRect sceneBounds = [self bounds];
241         NSRect frame = [self frame];
242         
243     minX = NSMinX(sceneBounds);
244         minY = NSMinY(sceneBounds);
245         maxX = NSMaxX(sceneBounds);
246         maxY = NSMaxY(sceneBounds);
247     
248 //    if(rendering)
249 //        glViewport(0, 0, (GLsizei)ProjectMovieSize.size.width, (GLsizei)ProjectMovieSize.size.height);
250 //    else
251         glViewport(0, 0, (GLsizei)frame.size.width, (GLsizei)frame.size.height);        // set the viewport
252     
253     glMatrixMode(GL_MODELVIEW);    // select the modelview matrix
254     glLoadIdentity();              // reset it
255     
256     glMatrixMode(GL_PROJECTION);   // select the projection matrix
257     glLoadIdentity();              // reset it
258     
259 //    if(rendering)
260 //        gluOrtho2D(minX, minX + ProjectMovieSize.size.width, minY, minY + ProjectMovieSize.size.height);
261 //    else
262         gluOrtho2D(minX, maxX, minY, maxY);     // define a 2-D orthographic projection matrix
263     
264 //    float scale;
265 //    if(frame.size.height < frame.size.width)
266 //        scale = frame.size.height/ProjectMovieSize.size.height;
267 //    else 
268 //        scale = frame.size.width/ProjectMovieSize.size.width;
269     
270 //    glScalef(scale, scale, 1.0);
271     
272         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
273     glEnable(GL_BLEND);
274
275 }
276
277 - (void)stopDisplayLink
278 {
279     [startTime release];
280     startTime = nil;
281     CVDisplayLinkStop(displayLink);
282 }
283
284 - (void)startDisplayLink
285 {
286     startTime = [[NSDate alloc] init];
287     CVDisplayLinkStart(displayLink);
288 }
289
290 - (void)seek:(QTTime)time
291 {
292     timeOffset = time;
293 }
294
295 - (void)getCurrentPixelData:(NSRect)rect buffer:(void*)buffer
296 {
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);
302     
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);
305     
306     glPopClientAttrib();
307 }
308
309 @end