OSDN Git Service

add small window mode
[eliscolors/main.git] / ElisLayer.m
1 //
2 //  ElisLayer.m
3 //  Elis Colors
4 //
5 //  Created by 柳 on 09/09/12.
6 //  Copyright 2009 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "ElisLayer.h"
10
11 static float convertQTTimeToSecond(QTTime t)
12 {
13     return (float)t.timeValue/t.timeScale;
14 }
15
16 @implementation ElisLayer
17
18 @synthesize media;
19
20 - (id)init
21 {
22     self.media = nil;
23 //    position.x = 0;
24 //    position.y = 0;
25     offset = QTZeroTime;
26     effects = [[NSMutableArray alloc] init];
27     pxKeyframe = [[ElisKeyframe alloc] init];
28     pyKeyframe = [[ElisKeyframe alloc] init];
29     [pxKeyframe setValueForTime:0.0 time:QTZeroTime];
30     [pyKeyframe setValueForTime:0.0 time:QTZeroTime];
31     
32     [self addEffect:@"CIOpacity"]; //デフォルトで透過度フィルタと
33 //    [self addEffect:@"CILanczosScaleTransform"]; // 拡大縮小フィルタと
34     [self addEffect:@"CIAffineTransform"]; // アフィン変換フィルタはつけておく。
35     
36   
37     return self;
38 }
39
40 - (void)setAlayer:(CALayer *)layer
41 {
42     alayer = layer;
43     
44     [layer setValue:self forKey:@"ElisLayer"];
45     
46     // layer.frameをバインド。
47     [layer addObserver:self 
48             forKeyPath:@"frame" 
49                options:(NSKeyValueObservingOptionNew) 
50                context:NULL];
51 }
52
53 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
54 {
55     [self changeMapping];
56 }
57
58 - (void)addEffect:(NSString*)name
59 {
60     [effects addObject:[[ElisEffect alloc] initWithName:name]];
61 }
62
63 // mappingとtrackNumberを変化させる。
64 - (void)changeMapping
65 {
66     CGRect frame = alayer.frame;
67     QTTime begin = QTMakeTime(frame.origin.x*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
68     QTTime d = QTMakeTime(frame.size.width*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
69     
70     trackNumber = floor(frame.origin.y/51.0);
71     mapping = QTMakeTimeRange(begin, d);
72 }
73
74 - (void)changeOffset:(float)df
75 {
76     QTTime new_offset = QTTimeIncrement(offset, QTMakeTime(df*DEFAULT_FPS/timeLineScale, DEFAULT_FPS));
77     
78     offset = new_offset;
79 }
80
81 - (BOOL)canChangeMapping:(CGRect)rect
82 {
83     QTTime duration;
84     
85     if([[media type] isEqualToString:@"image"])
86         duration = QTMakeTime(60*10, 1);
87     else
88         duration = [media duration];
89     
90     QTTime wantDuration = QTMakeTime(rect.size.width*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
91     float d = convertQTTimeToSecond(duration) - convertQTTimeToSecond(offset);
92     float wd = convertQTTimeToSecond(wantDuration);
93     
94     return 0.5 <= wd && wd <= d;
95 }
96
97 - (BOOL)canChangeOffset:(float)df
98 {
99     float now_offset = convertQTTimeToSecond(offset);
100     float duration = convertQTTimeToSecond([media duration]);
101     df /= timeLineScale;
102     
103     return 0.0 <= df + now_offset && df + now_offset <= duration;
104 }
105
106 - (BOOL)isInclude:(QTTime)time
107 {
108     float t = convertQTTimeToSecond(time);
109     float begin = convertQTTimeToSecond(mapping.time);
110     return begin <= t && t <= begin + convertQTTimeToSecond(mapping.duration);
111 //    return QTTimeInTimeRange(time, mapping); // これだとマルチスレッドにできなくね?
112 }
113
114 - (int)trackNumber
115 {
116     return trackNumber;
117 }
118
119 - (void)setPositionX:(float)x forTime:(QTTime)time
120 {
121     if(recording)
122         [pxKeyframe setValueForTime:x time:time];
123     else
124         [pxKeyframe setValueForTime:x time:QTZeroTime];
125 }
126
127 - (void)setPositionY:(float)y forTime:(QTTime)time
128 {
129     if(recording)
130         [pyKeyframe setValueForTime:y time:time];
131     else 
132         [pyKeyframe setValueForTime:y time:QTZeroTime];
133 }
134
135 - (CIImage*)getEffectedImage:(CVTimeStamp*)timeStamp forTime:(QTTime)time
136 {
137     QTTime innerTime = QTTimeDecrement(time, mapping.time);
138     CIImage* image = [media getFrameForTime:timeStamp];
139     if(image == nil) return nil;
140     
141     return [self applyEffects:image forTime:QTTimeIncrement(innerTime, offset)];
142 }
143
144 - (CIImage*)getEffectedImageWithoutStamp:(QTTime)time
145 {
146     QTTime innerTime = QTTimeDecrement(time, mapping.time);
147     CIImage* image = [media getFrameForQTTime:QTTimeIncrement(innerTime, offset)];
148     if(image == nil) return nil;
149     
150     return [self applyEffects:image forTime:QTTimeIncrement(innerTime, offset)];    
151 }
152
153 - (CIImage*)applyEffects:(CIImage*)image forTime:(QTTime)time
154 {
155     int i, size = [effects count];
156     ElisEffect* ef;
157     
158     for(i = 0; i < size; i++){
159         ef = [effects objectAtIndex:i];
160         [ef setInputImage:image];
161         image = [ef getImage:time];
162     }
163     
164     return image;
165 }    
166
167 - (NSPoint)getPositionForTime:(QTTime)time
168 {
169     float x = [pxKeyframe getValueForTime:time];
170     float y = [pyKeyframe getValueForTime:time];
171     
172     return NSMakePoint(x, y);
173 }
174
175 - (void)play
176 {
177     [media play];
178 }
179
180 - (void)stop
181 {
182     [media stop];
183 }
184
185 - (void)releaseContext
186 {
187     [media releaseContext];
188 }
189
190 - (QTTimeRange)mapping
191 {
192     return mapping;
193 }
194
195 - (void)seek:(QTTime)time
196 {
197     if([self isInclude:time]){
198         QTTime innerTime = QTTimeDecrement(time, mapping.time); // レイヤー内相対時間へ変換
199         [media setCurrentTime:QTTimeIncrement(innerTime, offset)];
200     } else {
201         [media setCurrentTime:offset];
202     }
203 }
204
205
206 // for Property Table
207 - (void)createPropertyTableDataSource:(NSMutableArray*)t_effects
208                              property:(NSMutableArray*)t_propertyNames
209                                 value:(NSMutableArray*)t_valueNames
210 {
211     NSMutableDictionary* params;
212     NSArray* arr;
213     NSString* paramName, *effectName;
214     NSDictionary* dict;
215     
216     [t_propertyNames addObject:@"Position X"];
217     [t_effects addObject:self];
218     [t_valueNames addObject:@""];
219     [t_propertyNames addObject:@"Position Y"];
220     [t_effects addObject:self];
221     [t_valueNames addObject:@""];
222     
223     int i, size = [effects count];
224     for(i = 0; i < size; i++){
225         params = [[effects objectAtIndex:i] getParamDictionary];
226         arr = [params allKeys];
227         arr = [arr sortedArrayUsingSelector:@selector(compare:)];
228         effectName = [[effects objectAtIndex:i] getName];
229         for(paramName in arr){
230             [t_propertyNames addObject:[NSString stringWithFormat:@"%@ %@", effectName, [paramName substringFromIndex:5]]];
231             [t_effects addObject:[effects objectAtIndex:i]];
232             [t_valueNames addObject:paramName];
233         }
234     }
235 }
236
237 - (QTTime)convertToInnnerTime:(QTTime)globalTime
238 {
239     return QTTimeIncrement(QTTimeDecrement(globalTime, mapping.time), offset);
240 }
241
242 - (QTTime)plusOffsetTime:(QTTime)time
243 {
244     return QTTimeIncrement(time, offset);
245 }
246
247 - (void)finalize
248 {
249     [alayer removeObserver:self forKeyPath:@"frame"];
250     [super finalize];
251 }
252
253 - (void)removePositionXKeyframe
254 {
255     pxKeyframe = [[ElisKeyframe alloc] init];
256     [pxKeyframe setValueForTime:0.0 time:QTZeroTime];
257 }
258
259 - (void)removePositionYKerframe
260 {
261     pyKeyframe = [[ElisKeyframe alloc] init];
262     [pyKeyframe setValueForTime:0.0 time:QTZeroTime];
263 }
264
265 - (void)removeEffect:(ElisEffect*)ef
266 {
267     [effects removeObject:ef];
268 }
269
270 - (void)getSoundTrack:(NSMutableArray*)soundTrack
271 {
272     QTTrack* t;
273     t = [media getSoundTrack];
274     if(t){
275         [soundTrack addObject:t];
276         [soundTrack addObject:[NSValue valueWithQTTime:offset]];
277         [soundTrack addObject:[NSValue valueWithQTTimeRange:mapping]];
278     }
279 }
280
281 - (void)encodeWithCoder:(NSCoder*)encoder
282 {
283     [encoder encodeObject:media forKey:@"media"];
284     [encoder encodeInt:trackNumber forKey:@"trackNumber"];
285     [encoder encodeObject:QTStringFromTimeRange(mapping) forKey:@"mapping"];
286     [encoder encodeObject:QTStringFromTime(offset) forKey:@"offset"];
287     [encoder encodeObject:effects forKey:@"effects"];
288     [encoder encodeObject:pxKeyframe forKey:@"pxKerframe"];
289     [encoder encodeObject:pyKeyframe forKey:@"pyKeyframe"];
290     
291     NSLog(@"encoding layer");
292 }
293
294 - (id)initWithCoder:(NSCoder*)coder
295 {
296     media = [coder decodeObjectForKey:@"media"];
297     trackNumber = [coder decodeIntForKey:@"trackNumber"];
298     mapping = QTTimeRangeFromString([coder decodeObjectForKey:@"mapping"]);
299     offset = QTTimeFromString([coder decodeObjectForKey:@"offset"]);
300     effects = [coder decodeObjectForKey:@"effects"];
301     pxKeyframe = [coder decodeObjectForKey:@"pxKeyframe"];
302     pyKeyframe = [coder decodeObjectForKey:@"pyKeyframe"];
303     
304     NSLog(@"decoding layer");
305     
306     return self;
307 }
308
309 - (void)setLayer:(CALayer*)layer
310 {
311     layer.frame = CGRectMake(convertQTTimeToSecond(mapping.time)*timeLineScale, trackNumber*51+1,
312                              (convertQTTimeToSecond(mapping.time) + convertQTTimeToSecond(mapping.duration))*timeLineScale, 50);
313     [self setAlayer:layer];
314 }
315
316 - (float)duration
317 {
318     return convertQTTimeToSecond(mapping.time) + convertQTTimeToSecond(mapping.duration);
319 }
320
321 - (NSString*)getPath
322 {
323     return [[media path] lastPathComponent];
324 }
325
326 - (NSString*)getType
327 {
328     return [media type];
329 }
330
331 @end