OSDN Git Service

first commit
[eliscolors/main.git] / ElisController.m
1 //
2 //  ElisController.m
3 //  Elis Colors
4 //
5 //  Created by 柳 on 09/09/12.
6 //  Copyright 2009 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "ElisController.h"
10
11
12 static float convertQTTimeToSecond(QTTime t)
13 {
14     return (float)t.timeValue/t.timeScale;
15 }
16
17 @implementation ElisController
18
19 - (void)awakeFromNib
20 {
21     layers = [[NSMutableArray alloc] init];
22     _animationLayerFactory = [[ElisAnimationLayerFactory alloc] init];
23     playing = NO;
24     recording = NO;
25     
26     ProjectMovieSize = CGRectMake(0, 0, 640, 480);
27     
28     // カスタムフィルタを初期化。
29     [ElisCustomFilter class];
30     
31     NSLog(@"Building effects ...");
32     // エフェクトメニューを構築。
33     [self buildEffectMenu];
34 }
35
36 - (CALayer*)createNewLayer:(NSString*)path
37 {
38     ElisLayer* layer;
39     CALayer* alayer;
40     ElisMedia* m;
41     layer = [[ElisLayer alloc] init];
42     m = [[ElisMedia alloc] initWithMovieFile:path];
43     layer.media = m;
44     alayer = [_animationLayerFactory createNewMovieLayer:convertQTTimeToSecond([m duration]) name:[path lastPathComponent]];
45 //    [alayer setValue:layer forKey:@"ElisLayer"];
46
47     [layer setAlayer:alayer];
48     [layers addObject:layer];
49     
50     return alayer;
51 }
52
53 // 絶対時間qttimeと関係があるレイヤーをまとめて返す。
54 - (void)getFrameForTime:(QTTime)qttime result:(NSMutableArray*)layerSet
55 {
56     int i, size = [layers count];
57     ElisLayer* l;
58     
59     // 再生時間オーバー。停止。
60     if(convertQTTimeToSecond(qttime) >= hipTime){
61         [_mainView stopDisplayLink];
62         [self stop:qttime];
63         return;
64     }
65     
66     globalCurrentTime = qttime;
67     [self moveSliderTo:qttime];
68     [_tableController reload];
69     
70     // GCDなりOpenMPなりで並列化すること。
71     for(i = 0; i < size; i++){
72         l = [layers objectAtIndex:i];
73         if([l isInclude:qttime]){
74             if(playing) [l play];
75             [layerSet addObject:l];
76         }else{
77             if(playing) [l stop];
78         }
79     }
80 }
81
82 - (void)play:(QTTime)time
83 {
84     NSMutableArray* interestLayers = [[NSMutableArray alloc] init];
85     int i, size = [layers count];
86     
87     hipTime = [self getHipTime];
88     
89     for(i = 0; i < size; i++)
90         if([[layers objectAtIndex:i] isInclude:time])
91             [interestLayers addObject:[layers objectAtIndex:i]];
92     
93     size = [interestLayers count];
94
95     for(i = 0; i < size; i++)
96         [(ElisLayer*)[interestLayers objectAtIndex:i] play];
97     
98     playing = YES;
99 }
100
101 - (void)stop:(QTTime)time
102 {
103     NSMutableArray* interestLayers = [[NSMutableArray alloc] init];
104     int i, size = [layers count];
105     
106 //    hipTime = [self getHipTime];
107 //    
108 //    for(i = 0; i < size; i++)
109 ////        if([[layers objectAtIndex:i] isInclude:time])
110 //        [interestLayers addObject:[layers objectAtIndex:i]];
111 //    
112 //    size = [interestLayers count];
113 //    
114 //    for(i = 0; i < size; i++)
115 //        [(ElisLayer*)[interestLayers objectAtIndex:i] stop];
116     
117     for(i = 0; i < size; i++)
118         [[layers objectAtIndex:i] stop];
119     
120     playing = NO;
121     globalCurrentTime = time;
122     _currentTime = time;
123 }
124
125 - (IBAction)startPlay:(id)sender
126 {
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];
132 }
133
134 - (IBAction)stopPlay:(id)sender
135 {
136     hipTime = [self getHipTime];
137     QTTime currentTime = QTMakeTime([timeSlider floatValue] * hipTime * DEFAULT_FPS, DEFAULT_FPS);
138     [self stop:currentTime];
139     [_mainView stopDisplayLink];
140 }
141     
142 - (float)getHipTime
143 {
144     int i, size = [layers count];
145     float hipTimeSecond = 0.0f, candidate;
146     
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;
152     }
153
154     return hipTimeSecond;
155 }
156
157 - (void)moveSliderTo:(QTTime)time
158 {
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];
163 }
164
165 - (IBAction)timeSliderChanged:(id)sender
166 {
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;
172     [self refresh];
173 }
174
175 - (void)seek:(QTTime)time
176 {
177     int i, size = [layers count];
178     [_mainView seek:time];
179
180     for(i = 0; i < size; i++)
181         [[layers objectAtIndex:i] seek:time];
182 }
183
184 - (void)refresh
185 {
186     if(playing) return;
187     hipTime = [self getHipTime];
188     [_mainView getFrameForQTTime:_currentTime];
189 }
190
191 - (IBAction)deleteSelectLayer:(id)sender
192 {
193     CALayer* selected = [_timeLineController getSelectLayer];
194     ElisLayer* layer = [selected valueForKey:@"ElisLayer"];
195     
196     [layers removeObject:layer];
197     [selected removeFromSuperlayer];
198     [_timeLineController removeSelectLayer];
199     [_tableController createPropertyTable:nil];
200     [_tableController reload];
201     [self refresh];
202 }
203
204 - (IBAction)recordingStateChanged:(id)sender
205 {
206     recording = !recording;
207 }
208
209 - (IBAction)removeAllKeyFrame:(id)sender
210 {
211     [_tableController removeAllKeyframe];
212     [self refresh];
213 }
214
215 - (IBAction)removeEffect:(id)sender
216 {
217     [_tableController removeEffect];
218     [self refresh];
219 }
220
221 - (IBAction)writeToFile:(id)sender
222 {
223     ElisWriter* writer = [[ElisWriter alloc] init];
224     [writer setView:_mainView];
225     [writer setContoller:self];
226     
227     [writer write:@"/Users/yanagi/Desktop/result.mov"];
228 }
229
230 // エフェクトのメニュー項目を構築
231 - (void)buildEffectMenu
232 {
233     NSArray* filterNames;
234     CIFilter* filter;
235     NSDictionary* attrs;
236     filterNames = [CIFilter filterNamesInCategories:[NSArray arrayWithObjects:
237                                                      kCICategoryDistortionEffect,
238                                                      kCICategoryGeometryAdjustment,
239                                                      kCICategoryCompositeOperation,
240                                                      kCICategoryHalftoneEffect,
241                                                      kCICategoryColorAdjustment,
242                                                      kCICategoryColorEffect,
243                                                      kCICategoryTransition,
244                                                      kCICategoryTileEffect,
245                                                      kCICategoryGenerator,
246                                                      kCICategoryGradient,
247                                                      kCICategoryStylize,
248                                                      kCICategorySharpen,
249                                                      kCICategoryBlur,
250                                                      nil]];
251     
252     NSString* name;
253     NSArray* inputKeys;
254     id elm;
255     NSMenuItem* item = [[NSMenuItem alloc] init], *child;
256     NSMenu* menu = [[NSMenu alloc] init];
257     int c = 0;
258     
259     [item setTitle:@"Effect"];
260     [menu setTitle:@"Effect"];
261     
262     filterNames = [CIFilter filterNamesInCategory:kCICategoryBuiltIn];
263     
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;
272             }
273             if(!([[[attrs valueForKey:elm] valueForKey:kCIAttributeClass] isEqualToString:@"NSNumber"] || 
274                  [[[attrs valueForKey:elm] valueForKey:kCIAttributeClass] isEqualToString:@"CIColor"])){
275                 goto jimp;
276             }
277         }
278     ok:
279         child = [[[NSMenuItem alloc] init] autorelease];
280         [child setTitle:name];
281         [child setAction:@selector(effectMenuPushed:)];
282         [child setTarget:self];
283         c++;
284         
285         [menu addItem:child];
286         //        [menu addItemWithTitle:name action:@selector(effectMenuPushed:) keyEquivalent:@""];
287         
288     jimp:
289         ;
290         //        [filter release];
291     }
292     NSLog(@"%d effetcs usable.", c);
293     [item setSubmenu:menu];
294     [menu setAutoenablesItems:NO];
295     [item setEnabled:YES];
296     [menu release];
297     [[NSApp mainMenu] insertItem:item atIndex:5];
298     [item setTarget:self];
299 }
300
301 - (void)effectMenuPushed:(id)sender
302 {
303     CALayer* l;
304     l = [_timeLineController getSelectLayer];
305     [[l valueForKey:@"ElisLayer"] addEffect:[sender title]];
306     [self refresh];
307     [_tableController createPropertyTable:[l valueForKey:@"ElisLayer"]];
308 }
309
310
311 @end