5 // Created by 柳 on 09/09/12.
6 // Copyright 2009 __MyCompanyName__. All rights reserved.
9 #import "ElisController.h"
12 static float convertQTTimeToSecond(QTTime t)
14 return (float)t.timeValue/t.timeScale;
17 @implementation ElisController
21 layers = [[NSMutableArray alloc] init];
22 _animationLayerFactory = [[ElisAnimationLayerFactory alloc] init];
26 ProjectMovieSize = CGRectMake(0, 0, 640, 480);
29 [ElisCustomFilter class];
31 NSLog(@"Building effects ...");
33 [self buildEffectMenu];
36 - (CALayer*)createNewLayer:(NSString*)path
41 layer = [[ElisLayer alloc] init];
42 m = [[ElisMedia alloc] initWithMovieFile:path];
44 alayer = [_animationLayerFactory createNewMovieLayer:convertQTTimeToSecond([m duration]) name:[path lastPathComponent]];
45 // [alayer setValue:layer forKey:@"ElisLayer"];
47 [layer setAlayer:alayer];
48 [layers addObject:layer];
53 // 絶対時間qttimeと関係があるレイヤーをまとめて返す。
54 - (void)getFrameForTime:(QTTime)qttime result:(NSMutableArray*)layerSet
56 int i, size = [layers count];
60 if(convertQTTimeToSecond(qttime) >= hipTime){
61 [_mainView stopDisplayLink];
66 globalCurrentTime = qttime;
67 [self moveSliderTo:qttime];
68 [_tableController reload];
70 // GCDなりOpenMPなりで並列化すること。
71 for(i = 0; i < size; i++){
72 l = [layers objectAtIndex:i];
73 if([l isInclude:qttime]){
75 [layerSet addObject:l];
82 - (void)play:(QTTime)time
84 NSMutableArray* interestLayers = [[NSMutableArray alloc] init];
85 int i, size = [layers count];
87 hipTime = [self getHipTime];
89 for(i = 0; i < size; i++)
90 if([[layers objectAtIndex:i] isInclude:time])
91 [interestLayers addObject:[layers objectAtIndex:i]];
93 size = [interestLayers count];
95 for(i = 0; i < size; i++)
96 [(ElisLayer*)[interestLayers objectAtIndex:i] play];
101 - (void)stop:(QTTime)time
103 NSMutableArray* interestLayers = [[NSMutableArray alloc] init];
104 int i, size = [layers count];
106 // hipTime = [self getHipTime];
108 // for(i = 0; i < size; i++)
109 //// if([[layers objectAtIndex:i] isInclude:time])
110 // [interestLayers addObject:[layers objectAtIndex:i]];
112 // size = [interestLayers count];
114 // for(i = 0; i < size; i++)
115 // [(ElisLayer*)[interestLayers objectAtIndex:i] stop];
117 for(i = 0; i < size; i++)
118 [[layers objectAtIndex:i] stop];
121 globalCurrentTime = time;
125 - (IBAction)startPlay:(id)sender
127 hipTime = [self getHipTime];
128 QTTime currentTime = QTMakeTime([timeSlider floatValue] * hipTime * DEFAULT_FPS, DEFAULT_FPS);
129 [self seek:currentTime];
130 [self play:currentTime];
131 [_mainView startDisplayLink];
134 - (IBAction)stopPlay:(id)sender
136 hipTime = [self getHipTime];
137 QTTime currentTime = QTMakeTime([timeSlider floatValue] * hipTime * DEFAULT_FPS, DEFAULT_FPS);
138 [self stop:currentTime];
139 [_mainView stopDisplayLink];
144 int i, size = [layers count];
145 float hipTimeSecond = 0.0f, candidate;
147 for(i = 0; i < size; i++){
148 candidate = convertQTTimeToSecond([[layers objectAtIndex:i] mapping].time)
149 + convertQTTimeToSecond([[layers objectAtIndex:i] mapping].duration);
150 if(candidate > hipTimeSecond)
151 hipTimeSecond = candidate;
154 return hipTimeSecond;
157 - (void)moveSliderTo:(QTTime)time
159 float now = convertQTTimeToSecond(time);
160 [timeSlider setFloatValue:now/hipTime];
161 [timeCodeField setStringValue:QTStringFromTime(QTMakeTime(now * DEFAULT_FPS, DEFAULT_FPS))];
162 [_timeLineController movePlaybackBar:now*timeLineScale];
165 - (IBAction)timeSliderChanged:(id)sender
167 float seconds = [sender floatValue];
168 QTTime currentTime = QTMakeTime(seconds * hipTime * DEFAULT_FPS, DEFAULT_FPS);
169 [timeCodeField setStringValue:QTStringFromTime(currentTime)];
170 _currentTime = currentTime;
171 globalCurrentTime = currentTime;
175 - (void)seek:(QTTime)time
177 int i, size = [layers count];
178 [_mainView seek:time];
180 for(i = 0; i < size; i++)
181 [[layers objectAtIndex:i] seek:time];
187 hipTime = [self getHipTime];
188 [_mainView getFrameForQTTime:_currentTime];
191 - (IBAction)deleteSelectLayer:(id)sender
193 CALayer* selected = [_timeLineController getSelectLayer];
194 ElisLayer* layer = [selected valueForKey:@"ElisLayer"];
196 [layers removeObject:layer];
197 [selected removeFromSuperlayer];
198 [_timeLineController removeSelectLayer];
199 [_tableController createPropertyTable:nil];
200 [_tableController reload];
204 - (IBAction)recordingStateChanged:(id)sender
206 recording = !recording;
209 - (IBAction)removeAllKeyFrame:(id)sender
211 [_tableController removeAllKeyframe];
215 - (IBAction)removeEffect:(id)sender
217 [_tableController removeEffect];
221 - (IBAction)writeToFile:(id)sender
223 ElisWriter* writer = [[ElisWriter alloc] init];
224 [writer setView:_mainView];
225 [writer setContoller:self];
227 [writer write:@"/Users/yanagi/Desktop/result.mov"];
231 - (void)buildEffectMenu
233 NSArray* filterNames;
236 filterNames = [CIFilter filterNamesInCategories:[NSArray arrayWithObjects:
237 kCICategoryDistortionEffect,
238 kCICategoryGeometryAdjustment,
239 kCICategoryCompositeOperation,
240 kCICategoryHalftoneEffect,
241 kCICategoryColorAdjustment,
242 kCICategoryColorEffect,
243 kCICategoryTransition,
244 kCICategoryTileEffect,
245 kCICategoryGenerator,
255 NSMenuItem* item = [[NSMenuItem alloc] init], *child;
256 NSMenu* menu = [[NSMenu alloc] init];
259 [item setTitle:@"Effect"];
260 [menu setTitle:@"Effect"];
262 filterNames = [CIFilter filterNamesInCategory:kCICategoryBuiltIn];
264 for(name in filterNames){
265 filter = [CIFilter filterWithName:name];
266 attrs = [filter attributes];
267 inputKeys = [filter inputKeys];
268 for(elm in inputKeys){
269 if([elm isEqualToString:@"inputImage"]) continue;
270 if([[[attrs valueForKey:elm] valueForKey:kCIAttributeClass] isEqualToString:@"CIVector"]){
271 if([[[attrs valueForKey:elm] valueForKey:kCIAttributeDefault] count] == 2) goto ok;
273 if(!([[[attrs valueForKey:elm] valueForKey:kCIAttributeClass] isEqualToString:@"NSNumber"] ||
274 [[[attrs valueForKey:elm] valueForKey:kCIAttributeClass] isEqualToString:@"CIColor"])){
279 child = [[[NSMenuItem alloc] init] autorelease];
280 [child setTitle:name];
281 [child setAction:@selector(effectMenuPushed:)];
282 [child setTarget:self];
285 [menu addItem:child];
286 // [menu addItemWithTitle:name action:@selector(effectMenuPushed:) keyEquivalent:@""];
292 NSLog(@"%d effetcs usable.", c);
293 [item setSubmenu:menu];
294 [menu setAutoenablesItems:NO];
295 [item setEnabled:YES];
297 [[NSApp mainMenu] insertItem:item atIndex:5];
298 [item setTarget:self];
301 - (void)effectMenuPushed:(id)sender
304 l = [_timeLineController getSelectLayer];
305 [[l valueForKey:@"ElisLayer"] addEffect:[sender title]];
307 [_tableController createPropertyTable:[l valueForKey:@"ElisLayer"]];